##// END OF EJS Templates
Removed hack from QCustomPlot, moved to QCustomPlotVect class.
jeandet -
r7:6e23aedd1ca8 default
parent child
Show More
This diff has been collapsed as it changes many lines, (619 lines changed) Show them Hide them
@@ -0,0 +1,619
1 #include "qcustomplotvect.h"
2 #include <QVector>
3 #include <QVectorIterator>
4 QCustomPlotVect::QCustomPlotVect(QWidget *parent)
5 :QCustomPlot(parent)
6 {
7
8 }
9
10 QCustomPlotVect::~QCustomPlotVect()
11 {
12
13 }
14
15 QCPGraphVect *QCustomPlotVect::addGraph(QCPAxis *keyAxis, QCPAxis *valueAxis)
16 {
17 if (!keyAxis) keyAxis = xAxis;
18 if (!valueAxis) valueAxis = yAxis;
19 if (!keyAxis || !valueAxis)
20 {
21 qDebug() << Q_FUNC_INFO << "can't use default QCustomPlot xAxis or yAxis, because at least one is invalid (has been deleted)";
22 return 0;
23 }
24 if (keyAxis->parentPlot() != this || valueAxis->parentPlot() != this)
25 {
26 qDebug() << Q_FUNC_INFO << "passed keyAxis or valueAxis doesn't have this QCustomPlot as parent";
27 return 0;
28 }
29
30 QCPGraphVect *newGraph = new QCPGraphVect(keyAxis, valueAxis);
31 if (addPlottable(newGraph))
32 {
33 newGraph->setName(QLatin1String("Graph ")+QString::number(mGraphs.size()));
34 return newGraph;
35 } else
36 {
37 delete newGraph;
38 return 0;
39 }
40 }
41
42
43 QCPGraphVect::QCPGraphVect(QCPAxis *keyAxis, QCPAxis *valueAxis)
44 :QCPGraph(keyAxis,valueAxis)
45 {
46 mData = new QVector<QCPData>();
47 }
48
49 QCPGraphVect::~QCPGraphVect()
50 {
51
52 }
53
54 void QCPGraphVect::setData(QVector<QCPData> *data)
55 {
56 if(data!=mData)
57 {
58 delete this->mData;
59 this->mData = data;
60 }
61 }
62
63 void QCPGraphVect::draw(QCPPainter *painter)
64 {
65 if (!mKeyAxis || !mValueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
66 int test = mKeyAxis.data()->range().size();
67 test = mData->count();
68 if (mKeyAxis.data()->range().size() <= 0 || mData->isEmpty()) return;
69 if (mLineStyle == lsNone && mScatterStyle.isNone()) return;
70
71 // allocate line and (if necessary) point vectors:
72 QVector<QPointF> *lineData = new QVector<QPointF>;
73 QVector<QCPData> *scatterData = 0;
74 if (!mScatterStyle.isNone())
75 scatterData = new QVector<QCPData>;
76
77 // fill vectors with data appropriate to plot style:
78 getPlotData(lineData, scatterData);
79
80 // check data validity if flag set:
81 #ifdef QCUSTOMPLOT_CHECK_DATA
82 QCPDataMap::const_iterator it;
83 for (it = mData->constBegin(); it != mData->constEnd(); ++it)
84 {
85 if (QCP::isInvalidData(it.value().key, it.value().value) ||
86 QCP::isInvalidData(it.value().keyErrorPlus, it.value().keyErrorMinus) ||
87 QCP::isInvalidData(it.value().valueErrorPlus, it.value().valueErrorPlus))
88 qDebug() << Q_FUNC_INFO << "Data point at" << it.key() << "invalid." << "Plottable name:" << name();
89 }
90 #endif
91
92 // draw fill of graph:
93 drawFill(painter, lineData);
94
95 // draw line:
96 if (mLineStyle == lsImpulse)
97 drawImpulsePlot(painter, lineData);
98 else if (mLineStyle != lsNone)
99 drawLinePlot(painter, lineData); // also step plots can be drawn as a line plot
100
101 // draw scatters:
102 if (scatterData)
103 drawScatterPlot(painter, scatterData);
104
105 // free allocated line and point vectors:
106 delete lineData;
107 if (scatterData)
108 delete scatterData;
109 }
110
111 void QCPGraphVect::getPlotData(QVector<QPointF> *lineData, QVector<QCPData> *scatterData) const
112 {
113 switch(mLineStyle)
114 {
115 case lsNone: getScatterPlotData(scatterData); break;
116 case lsLine: getLinePlotData(lineData, scatterData); break;
117 case lsStepLeft: getStepLeftPlotData(lineData, scatterData); break;
118 case lsStepRight: getStepRightPlotData(lineData, scatterData); break;
119 case lsStepCenter: getStepCenterPlotData(lineData, scatterData); break;
120 case lsImpulse: getImpulsePlotData(lineData, scatterData); break;
121 }
122 }
123
124 void QCPGraphVect::getLinePlotData(QVector<QPointF> *linePixelData, QVector<QCPData> *scatterData) const
125 {
126 QCPAxis *keyAxis = mKeyAxis.data();
127 QCPAxis *valueAxis = mValueAxis.data();
128 if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
129 if (!linePixelData) { qDebug() << Q_FUNC_INFO << "null pointer passed as linePixelData"; return; }
130
131 QVector<QCPData> lineData;
132 getPreparedData(&lineData, scatterData);
133 linePixelData->reserve(lineData.size()+2); // added 2 to reserve memory for lower/upper fill base points that might be needed for fill
134 linePixelData->resize(lineData.size());
135
136 // transform lineData points to pixels:
137 if (keyAxis->orientation() == Qt::Vertical)
138 {
139 for (int i=0; i<lineData.size(); ++i)
140 {
141 (*linePixelData)[i].setX(valueAxis->coordToPixel(lineData.at(i).value));
142 (*linePixelData)[i].setY(keyAxis->coordToPixel(lineData.at(i).key));
143 }
144 } else // key axis is horizontal
145 {
146 for (int i=0; i<lineData.size(); ++i)
147 {
148 (*linePixelData)[i].setX(keyAxis->coordToPixel(lineData.at(i).key));
149 (*linePixelData)[i].setY(valueAxis->coordToPixel(lineData.at(i).value));
150 }
151 }
152 }
153
154 QCPRange QCPGraphVect::getKeyRange(bool &foundRange, QCPAbstractPlottable::SignDomain inSignDomain, bool includeErrors) const
155 {
156
157 QCPRange range;
158 bool haveLower = false;
159 bool haveUpper = false;
160
161 double current, currentErrorMinus, currentErrorPlus;
162
163 if (inSignDomain == sdBoth) // range may be anywhere
164 {
165 QVector<QCPData>::const_iterator it = mData->constBegin();
166 while (it != mData->constEnd())
167 {
168 current = (*it).key;
169 currentErrorMinus = (includeErrors ? (*it).keyErrorMinus : 0);
170 currentErrorPlus = (includeErrors ? (*it).keyErrorPlus : 0);
171 if (current-currentErrorMinus < range.lower || !haveLower)
172 {
173 range.lower = current-currentErrorMinus;
174 haveLower = true;
175 }
176 if (current+currentErrorPlus > range.upper || !haveUpper)
177 {
178 range.upper = current+currentErrorPlus;
179 haveUpper = true;
180 }
181 ++it;
182 }
183 } else if (inSignDomain == sdNegative) // range may only be in the negative sign domain
184 {
185 QVector<QCPData>::const_iterator it = mData->constBegin();
186 while (it != mData->constEnd())
187 {
188 current = (*it).key;
189 currentErrorMinus = (includeErrors ? (*it).keyErrorMinus : 0);
190 currentErrorPlus = (includeErrors ? (*it).keyErrorPlus : 0);
191 if ((current-currentErrorMinus < range.lower || !haveLower) && current-currentErrorMinus < 0)
192 {
193 range.lower = current-currentErrorMinus;
194 haveLower = true;
195 }
196 if ((current+currentErrorPlus > range.upper || !haveUpper) && current+currentErrorPlus < 0)
197 {
198 range.upper = current+currentErrorPlus;
199 haveUpper = true;
200 }
201 if (includeErrors) // in case point is in valid sign domain but errobars stretch beyond it, we still want to geht that point.
202 {
203 if ((current < range.lower || !haveLower) && current < 0)
204 {
205 range.lower = current;
206 haveLower = true;
207 }
208 if ((current > range.upper || !haveUpper) && current < 0)
209 {
210 range.upper = current;
211 haveUpper = true;
212 }
213 }
214 ++it;
215 }
216 } else if (inSignDomain == sdPositive) // range may only be in the positive sign domain
217 {
218 QVector<QCPData>::const_iterator it = mData->constBegin();
219 while (it != mData->constEnd())
220 {
221 current = (*it).key;
222 currentErrorMinus = (includeErrors ? (*it).keyErrorMinus : 0);
223 currentErrorPlus = (includeErrors ? (*it).keyErrorPlus : 0);
224 if ((current-currentErrorMinus < range.lower || !haveLower) && current-currentErrorMinus > 0)
225 {
226 range.lower = current-currentErrorMinus;
227 haveLower = true;
228 }
229 if ((current+currentErrorPlus > range.upper || !haveUpper) && current+currentErrorPlus > 0)
230 {
231 range.upper = current+currentErrorPlus;
232 haveUpper = true;
233 }
234 if (includeErrors) // in case point is in valid sign domain but errobars stretch beyond it, we still want to get that point.
235 {
236 if ((current < range.lower || !haveLower) && current > 0)
237 {
238 range.lower = current;
239 haveLower = true;
240 }
241 if ((current > range.upper || !haveUpper) && current > 0)
242 {
243 range.upper = current;
244 haveUpper = true;
245 }
246 }
247 ++it;
248 }
249 }
250
251 foundRange = haveLower && haveUpper;
252 return range;
253 }
254
255 QCPRange QCPGraphVect::getValueRange(bool &foundRange, QCPAbstractPlottable::SignDomain inSignDomain, bool includeErrors) const
256 {
257 QCPRange range;
258 bool haveLower = false;
259 bool haveUpper = false;
260
261 double current, currentErrorMinus, currentErrorPlus;
262
263 if (inSignDomain == sdBoth) // range may be anywhere
264 {
265 QVector<QCPData>::const_iterator it = mData->constBegin();
266 while (it != mData->constEnd())
267 {
268 current = (*it).value;
269 currentErrorMinus = (includeErrors ? (*it).valueErrorMinus : 0);
270 currentErrorPlus = (includeErrors ? (*it).valueErrorPlus : 0);
271 if (current-currentErrorMinus < range.lower || !haveLower)
272 {
273 range.lower = current-currentErrorMinus;
274 haveLower = true;
275 }
276 if (current+currentErrorPlus > range.upper || !haveUpper)
277 {
278 range.upper = current+currentErrorPlus;
279 haveUpper = true;
280 }
281 ++it;
282 }
283 } else if (inSignDomain == sdNegative) // range may only be in the negative sign domain
284 {
285 QVector<QCPData>::const_iterator it = mData->constBegin();
286 while (it != mData->constEnd())
287 {
288 current = (*it).value;
289 currentErrorMinus = (includeErrors ? (*it).valueErrorMinus : 0);
290 currentErrorPlus = (includeErrors ? (*it).valueErrorPlus : 0);
291 if ((current-currentErrorMinus < range.lower || !haveLower) && current-currentErrorMinus < 0)
292 {
293 range.lower = current-currentErrorMinus;
294 haveLower = true;
295 }
296 if ((current+currentErrorPlus > range.upper || !haveUpper) && current+currentErrorPlus < 0)
297 {
298 range.upper = current+currentErrorPlus;
299 haveUpper = true;
300 }
301 if (includeErrors) // in case point is in valid sign domain but errobars stretch beyond it, we still want to get that point.
302 {
303 if ((current < range.lower || !haveLower) && current < 0)
304 {
305 range.lower = current;
306 haveLower = true;
307 }
308 if ((current > range.upper || !haveUpper) && current < 0)
309 {
310 range.upper = current;
311 haveUpper = true;
312 }
313 }
314 ++it;
315 }
316 } else if (inSignDomain == sdPositive) // range may only be in the positive sign domain
317 {
318 QVector<QCPData>::const_iterator it = mData->constBegin();
319 while (it != mData->constEnd())
320 {
321 current = (*it).value;
322 currentErrorMinus = (includeErrors ? (*it).valueErrorMinus : 0);
323 currentErrorPlus = (includeErrors ? (*it).valueErrorPlus : 0);
324 if ((current-currentErrorMinus < range.lower || !haveLower) && current-currentErrorMinus > 0)
325 {
326 range.lower = current-currentErrorMinus;
327 haveLower = true;
328 }
329 if ((current+currentErrorPlus > range.upper || !haveUpper) && current+currentErrorPlus > 0)
330 {
331 range.upper = current+currentErrorPlus;
332 haveUpper = true;
333 }
334 if (includeErrors) // in case point is in valid sign domain but errobars stretch beyond it, we still want to geht that point.
335 {
336 if ((current < range.lower || !haveLower) && current > 0)
337 {
338 range.lower = current;
339 haveLower = true;
340 }
341 if ((current > range.upper || !haveUpper) && current > 0)
342 {
343 range.upper = current;
344 haveUpper = true;
345 }
346 }
347 ++it;
348 }
349 }
350
351 foundRange = haveLower && haveUpper;
352 return range;
353 }
354
355 void QCPGraphVect::getPreparedData(QVector<QCPData> *lineData, QVector<QCPData> *scatterData) const
356 {
357 QCPAxis *keyAxis = mKeyAxis.data();
358 QCPAxis *valueAxis = mValueAxis.data();
359 if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
360 // get visible data range:
361 QVector<QCPData>::const_iterator lower, upper; // note that upper is the actual upper point, and not 1 step after the upper point
362 getVisibleDataBounds(lower, upper);
363 if (lower == mData->constEnd() || upper == mData->constEnd())
364 return;
365
366 // count points in visible range, taking into account that we only need to count to the limit maxCount if using adaptive sampling:
367 int maxCount = std::numeric_limits<int>::max();
368 if (mAdaptiveSampling)
369 {
370 int keyPixelSpan = qAbs(keyAxis->coordToPixel((*lower).key)-keyAxis->coordToPixel((*upper).key));
371 maxCount = 2*keyPixelSpan+2;
372 }
373 int dataCount = countDataInBounds(lower, upper, maxCount);
374
375 if (mAdaptiveSampling && dataCount >= maxCount) // use adaptive sampling only if there are at least two points per pixel on average
376 {
377 if (lineData)
378 {
379 QVector<QCPData>::const_iterator it = lower;
380 QVector<QCPData>::const_iterator upperEnd = upper+1;
381 double minValue = (*it).value;
382 double maxValue = (*it).value;
383 QVector<QCPData>::const_iterator currentIntervalFirstPoint = it;
384 int reversedFactor = keyAxis->rangeReversed() != (keyAxis->orientation()==Qt::Vertical) ? -1 : 1; // is used to calculate keyEpsilon pixel into the correct direction
385 int reversedRound = keyAxis->rangeReversed() != (keyAxis->orientation()==Qt::Vertical) ? 1 : 0; // is used to switch between floor (normal) and ceil (reversed) rounding of currentIntervalStartKey
386 double currentIntervalStartKey = keyAxis->pixelToCoord((int)(keyAxis->coordToPixel((*lower).key)+reversedRound));
387 double lastIntervalEndKey = currentIntervalStartKey;
388 double keyEpsilon = qAbs(currentIntervalStartKey-keyAxis->pixelToCoord(keyAxis->coordToPixel(currentIntervalStartKey)+1.0*reversedFactor)); // interval of one pixel on screen when mapped to plot key coordinates
389 bool keyEpsilonVariable = keyAxis->scaleType() == QCPAxis::stLogarithmic; // indicates whether keyEpsilon needs to be updated after every interval (for log axes)
390 int intervalDataCount = 1;
391 ++it; // advance iterator to second data point because adaptive sampling works in 1 point retrospect
392 while (it != upperEnd)
393 {
394 if ((*it).key < currentIntervalStartKey+keyEpsilon) // data point is still within same pixel, so skip it and expand value span of this cluster if necessary
395 {
396 if ((*it).value < minValue)
397 minValue = (*it).value;
398 else if ((*it).value > maxValue)
399 maxValue = (*it).value;
400 ++intervalDataCount;
401 } else // new pixel interval started
402 {
403 if (intervalDataCount >= 2) // last pixel had multiple data points, consolidate them to a cluster
404 {
405 if (lastIntervalEndKey < currentIntervalStartKey-keyEpsilon) // last point is further away, so first point of this cluster must be at a real data point
406 lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.2, (*currentIntervalFirstPoint).value));
407 lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.25, minValue));
408 lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.75, maxValue));
409 if ((*it).key > currentIntervalStartKey+keyEpsilon*2) // new pixel started further away from previous cluster, so make sure the last point of the cluster is at a real data point
410 lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.8, (*(it-1)).value));
411 } else
412 lineData->append(QCPData((*currentIntervalFirstPoint).key, (*currentIntervalFirstPoint).value));
413 lastIntervalEndKey = (*(it-1)).key;
414 minValue = (*it).value;
415 maxValue = (*it).value;
416 currentIntervalFirstPoint = it;
417 currentIntervalStartKey = keyAxis->pixelToCoord((int)(keyAxis->coordToPixel((*it).key)+reversedRound));
418 if (keyEpsilonVariable)
419 keyEpsilon = qAbs(currentIntervalStartKey-keyAxis->pixelToCoord(keyAxis->coordToPixel(currentIntervalStartKey)+1.0*reversedFactor));
420 intervalDataCount = 1;
421 }
422 ++it;
423 }
424 // handle last interval:
425 if (intervalDataCount >= 2) // last pixel had multiple data points, consolidate them to a cluster
426 {
427 if (lastIntervalEndKey < currentIntervalStartKey-keyEpsilon) // last point wasn't a cluster, so first point of this cluster must be at a real data point
428 lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.2, (*currentIntervalFirstPoint).value));
429 lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.25, minValue));
430 lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.75, maxValue));
431 } else
432 lineData->append(QCPData((*currentIntervalFirstPoint).key, (*currentIntervalFirstPoint).value));
433 }
434
435 if (scatterData)
436 {
437 double valueMaxRange = valueAxis->range().upper;
438 double valueMinRange = valueAxis->range().lower;
439 QVector<QCPData>::const_iterator it = lower;
440 QVector<QCPData>::const_iterator upperEnd = upper+1;
441 double minValue = (*it).value;
442 double maxValue = (*it).value;
443 QVector<QCPData>::const_iterator minValueIt = it;
444 QVector<QCPData>::const_iterator maxValueIt = it;
445 QVector<QCPData>::const_iterator currentIntervalStart = it;
446 int reversedFactor = keyAxis->rangeReversed() ? -1 : 1; // is used to calculate keyEpsilon pixel into the correct direction
447 int reversedRound = keyAxis->rangeReversed() ? 1 : 0; // is used to switch between floor (normal) and ceil (reversed) rounding of currentIntervalStartKey
448 double currentIntervalStartKey = keyAxis->pixelToCoord((int)(keyAxis->coordToPixel((*lower).key)+reversedRound));
449 double keyEpsilon = qAbs(currentIntervalStartKey-keyAxis->pixelToCoord(keyAxis->coordToPixel(currentIntervalStartKey)+1.0*reversedFactor)); // interval of one pixel on screen when mapped to plot key coordinates
450 bool keyEpsilonVariable = keyAxis->scaleType() == QCPAxis::stLogarithmic; // indicates whether keyEpsilon needs to be updated after every interval (for log axes)
451 int intervalDataCount = 1;
452 ++it; // advance iterator to second data point because adaptive sampling works in 1 point retrospect
453 while (it != upperEnd)
454 {
455 if ((*it).key < currentIntervalStartKey+keyEpsilon) // data point is still within same pixel, so skip it and expand value span of this pixel if necessary
456 {
457 if ((*it).value < minValue && (*it).value > valueMinRange && (*it).value < valueMaxRange)
458 {
459 minValue = (*it).value;
460 minValueIt = it;
461 } else if ((*it).value > maxValue && (*it).value > valueMinRange && (*it).value < valueMaxRange)
462 {
463 maxValue = (*it).value;
464 maxValueIt = it;
465 }
466 ++intervalDataCount;
467 } else // new pixel started
468 {
469 if (intervalDataCount >= 2) // last pixel had multiple data points, consolidate them
470 {
471 // determine value pixel span and add as many points in interval to maintain certain vertical data density (this is specific to scatter plot):
472 double valuePixelSpan = qAbs(valueAxis->coordToPixel(minValue)-valueAxis->coordToPixel(maxValue));
473 int dataModulo = qMax(1, qRound(intervalDataCount/(valuePixelSpan/4.0))); // approximately every 4 value pixels one data point on average
474 QVector<QCPData>::const_iterator intervalIt = currentIntervalStart;
475 int c = 0;
476 while (intervalIt != it)
477 {
478 if ((c % dataModulo == 0 || intervalIt == minValueIt || intervalIt == maxValueIt) && (*intervalIt).value > valueMinRange && (*intervalIt).value < valueMaxRange)
479 scatterData->append((*intervalIt));
480 ++c;
481 ++intervalIt;
482 }
483 } else if ((*currentIntervalStart).value > valueMinRange && (*currentIntervalStart).value < valueMaxRange)
484 scatterData->append((*currentIntervalStart));
485 minValue = (*it).value;
486 maxValue = (*it).value;
487 currentIntervalStart = it;
488 currentIntervalStartKey = keyAxis->pixelToCoord((int)(keyAxis->coordToPixel((*it).key)+reversedRound));
489 if (keyEpsilonVariable)
490 keyEpsilon = qAbs(currentIntervalStartKey-keyAxis->pixelToCoord(keyAxis->coordToPixel(currentIntervalStartKey)+1.0*reversedFactor));
491 intervalDataCount = 1;
492 }
493 ++it;
494 }
495 // handle last interval:
496 if (intervalDataCount >= 2) // last pixel had multiple data points, consolidate them
497 {
498 // determine value pixel span and add as many points in interval to maintain certain vertical data density (this is specific to scatter plot):
499 double valuePixelSpan = qAbs(valueAxis->coordToPixel(minValue)-valueAxis->coordToPixel(maxValue));
500 int dataModulo = qMax(1, qRound(intervalDataCount/(valuePixelSpan/4.0))); // approximately every 4 value pixels one data point on average
501 QVector<QCPData>::const_iterator intervalIt = currentIntervalStart;
502 int c = 0;
503 while (intervalIt != it)
504 {
505 if ((c % dataModulo == 0 || intervalIt == minValueIt || intervalIt == maxValueIt) && (*intervalIt).value > valueMinRange && (*intervalIt).value < valueMaxRange)
506 scatterData->append((*intervalIt));
507 ++c;
508 ++intervalIt;
509 }
510 } else if ((*currentIntervalStart).value > valueMinRange && (*currentIntervalStart).value < valueMaxRange)
511 scatterData->append(*currentIntervalStart);
512 }
513 } else // don't use adaptive sampling algorithm, transfer points one-to-one from the map into the output parameters
514 {
515 QVector<QCPData> *dataVector = 0;
516 if (lineData)
517 {
518 dataVector = lineData;
519 }
520 else if (scatterData)
521 dataVector = scatterData;
522 if (dataVector)
523 {
524 QVector<QCPData>::const_iterator it = lower;
525 QVector<QCPData>::const_iterator upperEnd = upper+1;
526 dataVector->reserve(dataCount+2); // +2 for possible fill end points
527 while (it != upperEnd)
528 {
529 dataVector->append(*it);
530 ++it;
531 }
532 }
533 if (lineData && scatterData)
534 *scatterData = *dataVector;
535 }
536 }
537
538 QVector<QCPData>::const_iterator __lowerBoundDico_vect(QVector<QCPData>* vector,double key)
539 {
540 int DX=vector->size()/2;
541 int pos=DX;
542 // double test=(*vector)[vector->length()-1].key;
543 if(key>((*vector)[vector->length()-1].key))
544 return vector->constEnd();
545 if(key<((*vector)[0].key))
546 return vector->constBegin();
547 while (DX>1)
548 {
549 DX=DX/2;
550 if((*vector)[pos].key > key)
551 {
552 pos-=DX;
553 }
554 else
555 {
556 pos+=DX;
557 }
558 }
559 if((*vector)[pos].key >= key)
560 return vector->constBegin()+pos;
561 return vector->constBegin()+pos+1;
562 }
563
564
565 QVector<QCPData>::const_iterator __upperBoundDico_vect(QVector<QCPData>* vector,double key)
566 {
567 int DX=vector->size()/2;
568 int pos=DX;
569 if(key>((*vector)[vector->length()-1].key))
570 return vector->constEnd();
571 if(key<((*vector)[0].key))
572 return vector->constBegin();
573 while (DX>1)
574 {
575 DX=DX/2;
576 if((*vector)[pos].key > key)
577 {
578 pos-=DX;
579 }
580 else
581 {
582 pos+=DX;
583 }
584 }
585 return vector->constBegin()+pos+1;
586 }
587
588
589 void QCPGraphVect::getVisibleDataBounds(QVector<QCPData>::const_iterator &lower, QVector<QCPData>::const_iterator &upper) const
590 {
591 if (!mKeyAxis) { qDebug() << Q_FUNC_INFO << "invalid key axis"; return; }
592 if (mData->isEmpty())
593 {
594 lower = mData->constEnd();
595 upper = mData->constEnd();
596 return;
597 }
598 QVector<QCPData>::const_iterator lbound = __lowerBoundDico_vect(mData,mKeyAxis.data()->range().lower);
599 QVector<QCPData>::const_iterator ubound = __upperBoundDico_vect(mData,mKeyAxis.data()->range().upper);
600 bool lowoutlier = lbound != mData->constBegin(); // indicates whether there exist points below axis range
601 bool highoutlier = ubound != mData->constEnd(); // indicates whether there exist points above axis range
602
603 lower = (lowoutlier ? lbound-1 : lbound); // data point range that will be actually drawn
604 upper = (highoutlier ? ubound : ubound-1); // data point range that will be actually drawn
605 }
606
607 int QCPGraphVect::countDataInBounds(const QVector<QCPData>::const_iterator &lower, const QVector<QCPData>::const_iterator &upper, int maxCount) const
608 {
609 if (upper == mData->constEnd() && lower == mData->constEnd())
610 return 0;
611 QVector<QCPData>::const_iterator it = lower;
612 int count = 1;
613 while (it != upper && count < maxCount)
614 {
615 ++it;
616 ++count;
617 }
618 return count;
619 }
@@ -0,0 +1,38
1 #ifndef QCUSTOMPLOTVECT_H
2 #define QCUSTOMPLOTVECT_H
3
4 #include <QWidget>
5 #include <qcustomplot.h>
6
7 class QCPGraphVect : public QCPGraph
8 {
9 Q_OBJECT
10 public:
11 explicit QCPGraphVect(QCPAxis *keyAxis, QCPAxis *valueAxis);
12 ~QCPGraphVect();
13 QVector<QCPData> *data() const { return mData; }
14 void setData(QVector<QCPData> *data);
15 protected:
16 QVector<QCPData>* mData;
17 virtual void draw(QCPPainter *painter);
18 virtual QCPRange getKeyRange(bool &foundRange, SignDomain inSignDomain, bool includeErrors) const; // overloads base class interface
19 virtual QCPRange getValueRange(bool &foundRange, SignDomain inSignDomain, bool includeErrors) const;
20 void getPreparedData(QVector<QCPData> *lineData, QVector<QCPData> *scatterData) const;
21 void getVisibleDataBounds(QVector<QCPData>::const_iterator &lower, QVector<QCPData>::const_iterator &upper) const;
22 int countDataInBounds(const QVector<QCPData>::const_iterator &lower, const QVector<QCPData>::const_iterator &upper, int maxCount) const;
23
24 void getPlotData(QVector<QPointF> *lineData, QVector<QCPData> *scatterData) const;
25 void getLinePlotData(QVector<QPointF> *linePixelData, QVector<QCPData> *scatterData) const;
26 };
27
28 class QCustomPlotVect : public QCustomPlot
29 {
30 Q_OBJECT
31 public:
32 QCustomPlotVect(QWidget *parent = 0);
33 ~QCustomPlotVect();
34 QCPGraphVect *addGraph(QCPAxis *keyAxis=0, QCPAxis *valueAxis=0);
35 protected:
36 };
37
38 #endif // QCUSTOMPLOTVECT_H
@@ -30,9 +30,7 SOURCES += src/main.cpp\
30 src/mainwindow.cpp \
30 src/mainwindow.cpp \
31 src/SocExplorerPlot.cpp \
31 src/SocExplorerPlot.cpp \
32 src/QCustomPlot/qcustomplot.cpp \
32 src/QCustomPlot/qcustomplot.cpp \
33 src/folderview.cpp \
34 src/toolbarcontainer.cpp \
33 src/toolbarcontainer.cpp \
35 src/folderlistwidget.cpp \
36 src/Core/abstractfileloader.cpp \
34 src/Core/abstractfileloader.cpp \
37 src/Core/filedownloader.cpp \
35 src/Core/filedownloader.cpp \
38 src/Core/filedownloadertask.cpp \
36 src/Core/filedownloadertask.cpp \
@@ -52,14 +50,13 SOURCES += src/main.cpp\
52 src/Core/Widgets/PyWdgt/pythonqtscriptingconsoledandd.cpp \
50 src/Core/Widgets/PyWdgt/pythonqtscriptingconsoledandd.cpp \
53 src/QCustomPlot/qcpdocumentobject.cpp \
51 src/QCustomPlot/qcpdocumentobject.cpp \
54 src/Core/Widgets/filebrowser.cpp \
52 src/Core/Widgets/filebrowser.cpp \
55 src/Core/Widgets/filesystemmodel.cpp
53 src/Core/Widgets/filesystemmodel.cpp \
54 src/Core/Widgets/qcustomplotvect.cpp
56
55
57 HEADERS += src/mainwindow.h \
56 HEADERS += src/mainwindow.h \
58 src/SocExplorerPlot.h \
57 src/SocExplorerPlot.h \
59 src/QCustomPlot/qcustomplot.h \
58 src/QCustomPlot/qcustomplot.h \
60 src/folderview.h \
61 src/toolbarcontainer.h \
59 src/toolbarcontainer.h \
62 src/folderlistwidget.h \
63 src/Core/abstractfileloader.h \
60 src/Core/abstractfileloader.h \
64 src/Core/filedownloader.h \
61 src/Core/filedownloader.h \
65 src/Core/filedownloadertask.h \
62 src/Core/filedownloadertask.h \
@@ -81,10 +78,10 HEADERS += src/mainwindow.h \
81 src/Core/pyqlop.h \
78 src/Core/pyqlop.h \
82 src/QCustomPlot/qcpdocumentobject.h \
79 src/QCustomPlot/qcpdocumentobject.h \
83 src/Core/Widgets/filebrowser.h \
80 src/Core/Widgets/filebrowser.h \
84 src/Core/Widgets/filesystemmodel.h
81 src/Core/Widgets/filesystemmodel.h \
82 src/Core/Widgets/qcustomplotvect.h
85
83
86 FORMS += src/mainwindow.ui \
84 FORMS += src/mainwindow.ui \
87 src/folderview.ui \
88 src/Core/Widgets/downloadhistory.ui \
85 src/Core/Widgets/downloadhistory.ui \
89 src/Core/Widgets/downloadhistoryelement.ui \
86 src/Core/Widgets/downloadhistoryelement.ui \
90 src/Cassini/cassinidatadownloader.ui \
87 src/Cassini/cassinidatadownloader.ui \
@@ -55,7 +55,7 void CassiniTools::makePlot()
55 plot->setXaxisTickLabelType(QCPAxis::ltDateTime);
55 plot->setXaxisTickLabelType(QCPAxis::ltDateTime);
56 plot->setXaxisDateTimeFormat("hh:mm:ss.zzz");
56 plot->setXaxisDateTimeFormat("hh:mm:ss.zzz");
57 plot->setContextMenuPolicy(Qt::ActionsContextMenu);
57 plot->setContextMenuPolicy(Qt::ActionsContextMenu);
58 QAction* action=new QAction("export view",_self);
58 SocExplorerPlotActions* action=new SocExplorerPlotActions("export view",plot->PID(),_self);
59 plot->addAction(action);
59 plot->addAction(action);
60 QObject::connect(action,SIGNAL(triggered()),_self,SLOT(export_view()));
60 QObject::connect(action,SIGNAL(triggered()),_self,SLOT(export_view()));
61 }
61 }
@@ -104,15 +104,11 void CassiniTools::plot_TAB_File(const Q
104 plotFile(fileName);
104 plotFile(fileName);
105 }
105 }
106
106
107 void CassiniTools::export_view()
107 void CassiniTools::export_view(int PID)
108 {
108 {
109 SocExplorerPlot* plot = QLopPlots::getPlot(m_defaultPlot);
109 SocExplorerPlot* plot = QLopPlots::getPlot(PID);
110 if(plot==NULL)
110 if(plot==NULL)
111 {
111 return;
112 makePlot();
113 plot = QLopPlots::getPlot(m_defaultPlot);
114 }
115 if(plot)
116 {
112 {
117 QString fileName = QFileDialog::getSaveFileName();
113 QString fileName = QFileDialog::getSaveFileName();
118 }
114 }
@@ -31,7 +31,7 public:
31 static void plotFile(const QString &File);
31 static void plotFile(const QString &File);
32 public slots:
32 public slots:
33 void plot_TAB_File(const QString& fileName);
33 void plot_TAB_File(const QString& fileName);
34 void export_view();
34 void export_view(int PID);
35 private slots:
35 private slots:
36 void dataReady(QLopDataList data);
36 void dataReady(QLopDataList data);
37 };
37 };
@@ -2,7 +2,6
2 #define CASSINITOOLSGUI_H
2 #define CASSINITOOLSGUI_H
3
3
4 #include <QWidget>
4 #include <QWidget>
5 #include <folderview.h>
6 #include <filebrowser.h>
5 #include <filebrowser.h>
7
6
8 namespace Ui {
7 namespace Ui {
@@ -79,6 +79,7 int QLopPlots::addPlot()
79 if(pid!=-1)
79 if(pid!=-1)
80 {
80 {
81 SocExplorerPlot* plot=new SocExplorerPlot();
81 SocExplorerPlot* plot=new SocExplorerPlot();
82 plot->setPID(pid);
82 m_plots->insert(pid,plot);
83 m_plots->insert(pid,plot);
83 QDockWidget* dock = new QDockWidget();
84 QDockWidget* dock = new QDockWidget();
84 dock->setWidget(plot);
85 dock->setWidget(plot);
@@ -4629,7 +4629,7 void PythonQtWrapper_QCPGraph::setErrorP
4629
4629
4630 void PythonQtWrapper_QCPGraph::setUseFastVectors(QCPGraph* theWrappedObject, bool useFastVectors)
4630 void PythonQtWrapper_QCPGraph::setUseFastVectors(QCPGraph* theWrappedObject, bool useFastVectors)
4631 {
4631 {
4632 ( theWrappedObject->setUseFastVectors(useFastVectors));
4632 // ( theWrappedObject->setUseFastVectors(useFastVectors));
4633 }
4633 }
4634
4634
4635 QPointF PythonQtWrapper_QCPGraph::upperFillBasePoint(QCPGraph* theWrappedObject, double upperKey) const
4635 QPointF PythonQtWrapper_QCPGraph::upperFillBasePoint(QCPGraph* theWrappedObject, double upperKey) const
@@ -4639,7 +4639,7 QPointF PythonQtWrapper_QCPGraph::upper
4639
4639
4640 bool PythonQtWrapper_QCPGraph::useFastVectors(QCPGraph* theWrappedObject) const
4640 bool PythonQtWrapper_QCPGraph::useFastVectors(QCPGraph* theWrappedObject) const
4641 {
4641 {
4642 return ( theWrappedObject->useFastVectors());
4642 return true;//( theWrappedObject->useFastVectors());
4643 }
4643 }
4644
4644
4645
4645
This diff has been collapsed as it changes many lines, (19433 lines changed) Show them Hide them
@@ -48,12 +48,12
48 Creates a new QCPPainter instance and sets default values
48 Creates a new QCPPainter instance and sets default values
49 */
49 */
50 QCPPainter::QCPPainter() :
50 QCPPainter::QCPPainter() :
51 QPainter(),
51 QPainter(),
52 mModes(pmDefault),
52 mModes(pmDefault),
53 mIsAntialiasing(false)
53 mIsAntialiasing(false)
54 {
54 {
55 // don't setRenderHint(QPainter::NonCosmeticDefautPen) here, because painter isn't active yet and
55 // don't setRenderHint(QPainter::NonCosmeticDefautPen) here, because painter isn't active yet and
56 // a call to begin() will follow
56 // a call to begin() will follow
57 }
57 }
58
58
59 /*!
59 /*!
@@ -63,13 +63,13 QCPPainter::QCPPainter() :
63 Like \ref begin, this method sets QPainter::NonCosmeticDefaultPen in Qt versions before Qt5.
63 Like \ref begin, this method sets QPainter::NonCosmeticDefaultPen in Qt versions before Qt5.
64 */
64 */
65 QCPPainter::QCPPainter(QPaintDevice *device) :
65 QCPPainter::QCPPainter(QPaintDevice *device) :
66 QPainter(device),
66 QPainter(device),
67 mModes(pmDefault),
67 mModes(pmDefault),
68 mIsAntialiasing(false)
68 mIsAntialiasing(false)
69 {
69 {
70 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) // before Qt5, default pens used to be cosmetic if NonCosmeticDefaultPen flag isn't set. So we set it to get consistency across Qt versions.
70 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) // before Qt5, default pens used to be cosmetic if NonCosmeticDefaultPen flag isn't set. So we set it to get consistency across Qt versions.
71 if (isActive())
71 if (isActive())
72 setRenderHint(QPainter::NonCosmeticDefaultPen);
72 setRenderHint(QPainter::NonCosmeticDefaultPen);
73 #endif
73 #endif
74 }
74 }
75
75
@@ -85,9 +85,9 QCPPainter::~QCPPainter()
85 */
85 */
86 void QCPPainter::setPen(const QPen &pen)
86 void QCPPainter::setPen(const QPen &pen)
87 {
87 {
88 QPainter::setPen(pen);
88 QPainter::setPen(pen);
89 if (mModes.testFlag(pmNonCosmetic))
89 if (mModes.testFlag(pmNonCosmetic))
90 makeNonCosmetic();
90 makeNonCosmetic();
91 }
91 }
92
92
93 /*! \overload
93 /*! \overload
@@ -99,9 +99,9 void QCPPainter::setPen(const QPen &pen)
99 */
99 */
100 void QCPPainter::setPen(const QColor &color)
100 void QCPPainter::setPen(const QColor &color)
101 {
101 {
102 QPainter::setPen(color);
102 QPainter::setPen(color);
103 if (mModes.testFlag(pmNonCosmetic))
103 if (mModes.testFlag(pmNonCosmetic))
104 makeNonCosmetic();
104 makeNonCosmetic();
105 }
105 }
106
106
107 /*! \overload
107 /*! \overload
@@ -113,9 +113,9 void QCPPainter::setPen(const QColor &co
113 */
113 */
114 void QCPPainter::setPen(Qt::PenStyle penStyle)
114 void QCPPainter::setPen(Qt::PenStyle penStyle)
115 {
115 {
116 QPainter::setPen(penStyle);
116 QPainter::setPen(penStyle);
117 if (mModes.testFlag(pmNonCosmetic))
117 if (mModes.testFlag(pmNonCosmetic))
118 makeNonCosmetic();
118 makeNonCosmetic();
119 }
119 }
120
120
121 /*! \overload
121 /*! \overload
@@ -128,10 +128,10 void QCPPainter::setPen(Qt::PenStyle pen
128 */
128 */
129 void QCPPainter::drawLine(const QLineF &line)
129 void QCPPainter::drawLine(const QLineF &line)
130 {
130 {
131 if (mIsAntialiasing || mModes.testFlag(pmVectorized))
131 if (mIsAntialiasing || mModes.testFlag(pmVectorized))
132 QPainter::drawLine(line);
132 QPainter::drawLine(line);
133 else
133 else
134 QPainter::drawLine(line.toLine());
134 QPainter::drawLine(line.toLine());
135 }
135 }
136
136
137 /*!
137 /*!
@@ -142,16 +142,16 void QCPPainter::drawLine(const QLineF &
142 */
142 */
143 void QCPPainter::setAntialiasing(bool enabled)
143 void QCPPainter::setAntialiasing(bool enabled)
144 {
144 {
145 setRenderHint(QPainter::Antialiasing, enabled);
145 setRenderHint(QPainter::Antialiasing, enabled);
146 if (mIsAntialiasing != enabled)
146 if (mIsAntialiasing != enabled)
147 {
147 {
148 mIsAntialiasing = enabled;
148 mIsAntialiasing = enabled;
149 if (!mModes.testFlag(pmVectorized)) // antialiasing half-pixel shift only needed for rasterized outputs
149 if (!mModes.testFlag(pmVectorized)) // antialiasing half-pixel shift only needed for rasterized outputs
150 {
150 {
151 if (mIsAntialiasing)
151 if (mIsAntialiasing)
152 translate(0.5, 0.5);
152 translate(0.5, 0.5);
153 else
153 else
154 translate(-0.5, -0.5);
154 translate(-0.5, -0.5);
155 }
155 }
156 }
156 }
157 }
157 }
@@ -162,7 +162,7 void QCPPainter::setAntialiasing(bool en
162 */
162 */
163 void QCPPainter::setModes(QCPPainter::PainterModes modes)
163 void QCPPainter::setModes(QCPPainter::PainterModes modes)
164 {
164 {
165 mModes = modes;
165 mModes = modes;
166 }
166 }
167
167
168 /*!
168 /*!
@@ -178,12 +178,12 void QCPPainter::setModes(QCPPainter::Pa
178 */
178 */
179 bool QCPPainter::begin(QPaintDevice *device)
179 bool QCPPainter::begin(QPaintDevice *device)
180 {
180 {
181 bool result = QPainter::begin(device);
181 bool result = QPainter::begin(device);
182 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) // before Qt5, default pens used to be cosmetic if NonCosmeticDefaultPen flag isn't set. So we set it to get consistency across Qt versions.
182 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) // before Qt5, default pens used to be cosmetic if NonCosmeticDefaultPen flag isn't set. So we set it to get consistency across Qt versions.
183 if (result)
183 if (result)
184 setRenderHint(QPainter::NonCosmeticDefaultPen);
184 setRenderHint(QPainter::NonCosmeticDefaultPen);
185 #endif
185 #endif
186 return result;
186 return result;
187 }
187 }
188
188
189 /*! \overload
189 /*! \overload
@@ -193,10 +193,10 bool QCPPainter::begin(QPaintDevice *dev
193 */
193 */
194 void QCPPainter::setMode(QCPPainter::PainterMode mode, bool enabled)
194 void QCPPainter::setMode(QCPPainter::PainterMode mode, bool enabled)
195 {
195 {
196 if (!enabled && mModes.testFlag(mode))
196 if (!enabled && mModes.testFlag(mode))
197 mModes &= ~mode;
197 mModes &= ~mode;
198 else if (enabled && !mModes.testFlag(mode))
198 else if (enabled && !mModes.testFlag(mode))
199 mModes |= mode;
199 mModes |= mode;
200 }
200 }
201
201
202 /*!
202 /*!
@@ -209,8 +209,8 void QCPPainter::setMode(QCPPainter::Pai
209 */
209 */
210 void QCPPainter::save()
210 void QCPPainter::save()
211 {
211 {
212 mAntialiasingStack.push(mIsAntialiasing);
212 mAntialiasingStack.push(mIsAntialiasing);
213 QPainter::save();
213 QPainter::save();
214 }
214 }
215
215
216 /*!
216 /*!
@@ -223,11 +223,11 void QCPPainter::save()
223 */
223 */
224 void QCPPainter::restore()
224 void QCPPainter::restore()
225 {
225 {
226 if (!mAntialiasingStack.isEmpty())
226 if (!mAntialiasingStack.isEmpty())
227 mIsAntialiasing = mAntialiasingStack.pop();
227 mIsAntialiasing = mAntialiasingStack.pop();
228 else
228 else
229 qDebug() << Q_FUNC_INFO << "Unbalanced save/restore";
229 qDebug() << Q_FUNC_INFO << "Unbalanced save/restore";
230 QPainter::restore();
230 QPainter::restore();
231 }
231 }
232
232
233 /*!
233 /*!
@@ -236,11 +236,11 void QCPPainter::restore()
236 */
236 */
237 void QCPPainter::makeNonCosmetic()
237 void QCPPainter::makeNonCosmetic()
238 {
238 {
239 if (qFuzzyIsNull(pen().widthF()))
239 if (qFuzzyIsNull(pen().widthF()))
240 {
240 {
241 QPen p = pen();
241 QPen p = pen();
242 p.setWidth(1);
242 p.setWidth(1);
243 QPainter::setPen(p);
243 QPainter::setPen(p);
244 }
244 }
245 }
245 }
246
246
@@ -340,11 +340,11 void QCPPainter::makeNonCosmetic()
340 from the plottable that uses this scatter style.
340 from the plottable that uses this scatter style.
341 */
341 */
342 QCPScatterStyle::QCPScatterStyle() :
342 QCPScatterStyle::QCPScatterStyle() :
343 mSize(6),
343 mSize(6),
344 mShape(ssNone),
344 mShape(ssNone),
345 mPen(Qt::NoPen),
345 mPen(Qt::NoPen),
346 mBrush(Qt::NoBrush),
346 mBrush(Qt::NoBrush),
347 mPenDefined(false)
347 mPenDefined(false)
348 {
348 {
349 }
349 }
350
350
@@ -356,11 +356,11 QCPScatterStyle::QCPScatterStyle() :
356 from the plottable that uses this scatter style.
356 from the plottable that uses this scatter style.
357 */
357 */
358 QCPScatterStyle::QCPScatterStyle(ScatterShape shape, double size) :
358 QCPScatterStyle::QCPScatterStyle(ScatterShape shape, double size) :
359 mSize(size),
359 mSize(size),
360 mShape(shape),
360 mShape(shape),
361 mPen(Qt::NoPen),
361 mPen(Qt::NoPen),
362 mBrush(Qt::NoBrush),
362 mBrush(Qt::NoBrush),
363 mPenDefined(false)
363 mPenDefined(false)
364 {
364 {
365 }
365 }
366
366
@@ -369,11 +369,11 QCPScatterStyle::QCPScatterStyle(Scatter
369 and size to \a size. No brush is defined, i.e. the scatter point will not be filled.
369 and size to \a size. No brush is defined, i.e. the scatter point will not be filled.
370 */
370 */
371 QCPScatterStyle::QCPScatterStyle(ScatterShape shape, const QColor &color, double size) :
371 QCPScatterStyle::QCPScatterStyle(ScatterShape shape, const QColor &color, double size) :
372 mSize(size),
372 mSize(size),
373 mShape(shape),
373 mShape(shape),
374 mPen(QPen(color)),
374 mPen(QPen(color)),
375 mBrush(Qt::NoBrush),
375 mBrush(Qt::NoBrush),
376 mPenDefined(true)
376 mPenDefined(true)
377 {
377 {
378 }
378 }
379
379
@@ -382,11 +382,11 QCPScatterStyle::QCPScatterStyle(Scatter
382 the brush color to \a fill (with a solid pattern), and size to \a size.
382 the brush color to \a fill (with a solid pattern), and size to \a size.
383 */
383 */
384 QCPScatterStyle::QCPScatterStyle(ScatterShape shape, const QColor &color, const QColor &fill, double size) :
384 QCPScatterStyle::QCPScatterStyle(ScatterShape shape, const QColor &color, const QColor &fill, double size) :
385 mSize(size),
385 mSize(size),
386 mShape(shape),
386 mShape(shape),
387 mPen(QPen(color)),
387 mPen(QPen(color)),
388 mBrush(QBrush(fill)),
388 mBrush(QBrush(fill)),
389 mPenDefined(true)
389 mPenDefined(true)
390 {
390 {
391 }
391 }
392
392
@@ -406,11 +406,11 QCPScatterStyle::QCPScatterStyle(Scatter
406 wanted.
406 wanted.
407 */
407 */
408 QCPScatterStyle::QCPScatterStyle(ScatterShape shape, const QPen &pen, const QBrush &brush, double size) :
408 QCPScatterStyle::QCPScatterStyle(ScatterShape shape, const QPen &pen, const QBrush &brush, double size) :
409 mSize(size),
409 mSize(size),
410 mShape(shape),
410 mShape(shape),
411 mPen(pen),
411 mPen(pen),
412 mBrush(brush),
412 mBrush(brush),
413 mPenDefined(pen.style() != Qt::NoPen)
413 mPenDefined(pen.style() != Qt::NoPen)
414 {
414 {
415 }
415 }
416
416
@@ -419,12 +419,12 QCPScatterStyle::QCPScatterStyle(Scatter
419 is set to \ref ssPixmap.
419 is set to \ref ssPixmap.
420 */
420 */
421 QCPScatterStyle::QCPScatterStyle(const QPixmap &pixmap) :
421 QCPScatterStyle::QCPScatterStyle(const QPixmap &pixmap) :
422 mSize(5),
422 mSize(5),
423 mShape(ssPixmap),
423 mShape(ssPixmap),
424 mPen(Qt::NoPen),
424 mPen(Qt::NoPen),
425 mBrush(Qt::NoBrush),
425 mBrush(Qt::NoBrush),
426 mPixmap(pixmap),
426 mPixmap(pixmap),
427 mPenDefined(false)
427 mPenDefined(false)
428 {
428 {
429 }
429 }
430
430
@@ -438,12 +438,12 QCPScatterStyle::QCPScatterStyle(const Q
438 natural size by default. To double the size of the path for example, set \a size to 12.
438 natural size by default. To double the size of the path for example, set \a size to 12.
439 */
439 */
440 QCPScatterStyle::QCPScatterStyle(const QPainterPath &customPath, const QPen &pen, const QBrush &brush, double size) :
440 QCPScatterStyle::QCPScatterStyle(const QPainterPath &customPath, const QPen &pen, const QBrush &brush, double size) :
441 mSize(size),
441 mSize(size),
442 mShape(ssCustom),
442 mShape(ssCustom),
443 mPen(pen),
443 mPen(pen),
444 mBrush(brush),
444 mBrush(brush),
445 mCustomPath(customPath),
445 mCustomPath(customPath),
446 mPenDefined(pen.style() != Qt::NoPen)
446 mPenDefined(pen.style() != Qt::NoPen)
447 {
447 {
448 }
448 }
449
449
@@ -454,7 +454,7 QCPScatterStyle::QCPScatterStyle(const Q
454 */
454 */
455 void QCPScatterStyle::setSize(double size)
455 void QCPScatterStyle::setSize(double size)
456 {
456 {
457 mSize = size;
457 mSize = size;
458 }
458 }
459
459
460 /*!
460 /*!
@@ -467,7 +467,7 void QCPScatterStyle::setSize(double siz
467 */
467 */
468 void QCPScatterStyle::setShape(QCPScatterStyle::ScatterShape shape)
468 void QCPScatterStyle::setShape(QCPScatterStyle::ScatterShape shape)
469 {
469 {
470 mShape = shape;
470 mShape = shape;
471 }
471 }
472
472
473 /*!
473 /*!
@@ -480,8 +480,8 void QCPScatterStyle::setShape(QCPScatte
480 */
480 */
481 void QCPScatterStyle::setPen(const QPen &pen)
481 void QCPScatterStyle::setPen(const QPen &pen)
482 {
482 {
483 mPenDefined = true;
483 mPenDefined = true;
484 mPen = pen;
484 mPen = pen;
485 }
485 }
486
486
487 /*!
487 /*!
@@ -492,7 +492,7 void QCPScatterStyle::setPen(const QPen
492 */
492 */
493 void QCPScatterStyle::setBrush(const QBrush &brush)
493 void QCPScatterStyle::setBrush(const QBrush &brush)
494 {
494 {
495 mBrush = brush;
495 mBrush = brush;
496 }
496 }
497
497
498 /*!
498 /*!
@@ -504,8 +504,8 void QCPScatterStyle::setBrush(const QBr
504 */
504 */
505 void QCPScatterStyle::setPixmap(const QPixmap &pixmap)
505 void QCPScatterStyle::setPixmap(const QPixmap &pixmap)
506 {
506 {
507 setShape(ssPixmap);
507 setShape(ssPixmap);
508 mPixmap = pixmap;
508 mPixmap = pixmap;
509 }
509 }
510
510
511 /*!
511 /*!
@@ -515,8 +515,8 void QCPScatterStyle::setPixmap(const QP
515 */
515 */
516 void QCPScatterStyle::setCustomPath(const QPainterPath &customPath)
516 void QCPScatterStyle::setCustomPath(const QPainterPath &customPath)
517 {
517 {
518 setShape(ssCustom);
518 setShape(ssCustom);
519 mCustomPath = customPath;
519 mCustomPath = customPath;
520 }
520 }
521
521
522 /*!
522 /*!
@@ -530,8 +530,8 void QCPScatterStyle::setCustomPath(cons
530 */
530 */
531 void QCPScatterStyle::applyTo(QCPPainter *painter, const QPen &defaultPen) const
531 void QCPScatterStyle::applyTo(QCPPainter *painter, const QPen &defaultPen) const
532 {
532 {
533 painter->setPen(mPenDefined ? mPen : defaultPen);
533 painter->setPen(mPenDefined ? mPen : defaultPen);
534 painter->setBrush(mBrush);
534 painter->setBrush(mBrush);
535 }
535 }
536
536
537 /*!
537 /*!
@@ -544,7 +544,7 void QCPScatterStyle::applyTo(QCPPainter
544 */
544 */
545 void QCPScatterStyle::drawShape(QCPPainter *painter, QPointF pos) const
545 void QCPScatterStyle::drawShape(QCPPainter *painter, QPointF pos) const
546 {
546 {
547 drawShape(painter, pos.x(), pos.y());
547 drawShape(painter, pos.x(), pos.y());
548 }
548 }
549
549
550 /*! \overload
550 /*! \overload
@@ -552,125 +552,125 void QCPScatterStyle::drawShape(QCPPaint
552 */
552 */
553 void QCPScatterStyle::drawShape(QCPPainter *painter, double x, double y) const
553 void QCPScatterStyle::drawShape(QCPPainter *painter, double x, double y) const
554 {
554 {
555 double w = mSize/2.0;
555 double w = mSize/2.0;
556 switch (mShape)
556 switch (mShape)
557 {
557 {
558 case ssNone: break;
558 case ssNone: break;
559 case ssDot:
559 case ssDot:
560 {
560 {
561 painter->drawLine(QPointF(x, y), QPointF(x+0.0001, y));
561 painter->drawLine(QPointF(x, y), QPointF(x+0.0001, y));
562 break;
562 break;
563 }
563 }
564 case ssCross:
564 case ssCross:
565 {
565 {
566 painter->drawLine(QLineF(x-w, y-w, x+w, y+w));
566 painter->drawLine(QLineF(x-w, y-w, x+w, y+w));
567 painter->drawLine(QLineF(x-w, y+w, x+w, y-w));
567 painter->drawLine(QLineF(x-w, y+w, x+w, y-w));
568 break;
568 break;
569 }
569 }
570 case ssPlus:
570 case ssPlus:
571 {
571 {
572 painter->drawLine(QLineF(x-w, y, x+w, y));
572 painter->drawLine(QLineF(x-w, y, x+w, y));
573 painter->drawLine(QLineF( x, y+w, x, y-w));
573 painter->drawLine(QLineF( x, y+w, x, y-w));
574 break;
574 break;
575 }
575 }
576 case ssCircle:
576 case ssCircle:
577 {
577 {
578 painter->drawEllipse(QPointF(x , y), w, w);
578 painter->drawEllipse(QPointF(x , y), w, w);
579 break;
579 break;
580 }
580 }
581 case ssDisc:
581 case ssDisc:
582 {
582 {
583 QBrush b = painter->brush();
583 QBrush b = painter->brush();
584 painter->setBrush(painter->pen().color());
584 painter->setBrush(painter->pen().color());
585 painter->drawEllipse(QPointF(x , y), w, w);
585 painter->drawEllipse(QPointF(x , y), w, w);
586 painter->setBrush(b);
586 painter->setBrush(b);
587 break;
587 break;
588 }
588 }
589 case ssSquare:
589 case ssSquare:
590 {
590 {
591 painter->drawRect(QRectF(x-w, y-w, mSize, mSize));
591 painter->drawRect(QRectF(x-w, y-w, mSize, mSize));
592 break;
592 break;
593 }
593 }
594 case ssDiamond:
594 case ssDiamond:
595 {
595 {
596 painter->drawLine(QLineF(x-w, y, x, y-w));
596 painter->drawLine(QLineF(x-w, y, x, y-w));
597 painter->drawLine(QLineF( x, y-w, x+w, y));
597 painter->drawLine(QLineF( x, y-w, x+w, y));
598 painter->drawLine(QLineF(x+w, y, x, y+w));
598 painter->drawLine(QLineF(x+w, y, x, y+w));
599 painter->drawLine(QLineF( x, y+w, x-w, y));
599 painter->drawLine(QLineF( x, y+w, x-w, y));
600 break;
600 break;
601 }
601 }
602 case ssStar:
602 case ssStar:
603 {
603 {
604 painter->drawLine(QLineF(x-w, y, x+w, y));
604 painter->drawLine(QLineF(x-w, y, x+w, y));
605 painter->drawLine(QLineF( x, y+w, x, y-w));
605 painter->drawLine(QLineF( x, y+w, x, y-w));
606 painter->drawLine(QLineF(x-w*0.707, y-w*0.707, x+w*0.707, y+w*0.707));
606 painter->drawLine(QLineF(x-w*0.707, y-w*0.707, x+w*0.707, y+w*0.707));
607 painter->drawLine(QLineF(x-w*0.707, y+w*0.707, x+w*0.707, y-w*0.707));
607 painter->drawLine(QLineF(x-w*0.707, y+w*0.707, x+w*0.707, y-w*0.707));
608 break;
608 break;
609 }
609 }
610 case ssTriangle:
610 case ssTriangle:
611 {
611 {
612 painter->drawLine(QLineF(x-w, y+0.755*w, x+w, y+0.755*w));
612 painter->drawLine(QLineF(x-w, y+0.755*w, x+w, y+0.755*w));
613 painter->drawLine(QLineF(x+w, y+0.755*w, x, y-0.977*w));
613 painter->drawLine(QLineF(x+w, y+0.755*w, x, y-0.977*w));
614 painter->drawLine(QLineF( x, y-0.977*w, x-w, y+0.755*w));
614 painter->drawLine(QLineF( x, y-0.977*w, x-w, y+0.755*w));
615 break;
615 break;
616 }
616 }
617 case ssTriangleInverted:
617 case ssTriangleInverted:
618 {
618 {
619 painter->drawLine(QLineF(x-w, y-0.755*w, x+w, y-0.755*w));
619 painter->drawLine(QLineF(x-w, y-0.755*w, x+w, y-0.755*w));
620 painter->drawLine(QLineF(x+w, y-0.755*w, x, y+0.977*w));
620 painter->drawLine(QLineF(x+w, y-0.755*w, x, y+0.977*w));
621 painter->drawLine(QLineF( x, y+0.977*w, x-w, y-0.755*w));
621 painter->drawLine(QLineF( x, y+0.977*w, x-w, y-0.755*w));
622 break;
622 break;
623 }
623 }
624 case ssCrossSquare:
624 case ssCrossSquare:
625 {
625 {
626 painter->drawLine(QLineF(x-w, y-w, x+w*0.95, y+w*0.95));
626 painter->drawLine(QLineF(x-w, y-w, x+w*0.95, y+w*0.95));
627 painter->drawLine(QLineF(x-w, y+w*0.95, x+w*0.95, y-w));
627 painter->drawLine(QLineF(x-w, y+w*0.95, x+w*0.95, y-w));
628 painter->drawRect(QRectF(x-w, y-w, mSize, mSize));
628 painter->drawRect(QRectF(x-w, y-w, mSize, mSize));
629 break;
629 break;
630 }
630 }
631 case ssPlusSquare:
631 case ssPlusSquare:
632 {
632 {
633 painter->drawLine(QLineF(x-w, y, x+w*0.95, y));
633 painter->drawLine(QLineF(x-w, y, x+w*0.95, y));
634 painter->drawLine(QLineF( x, y+w, x, y-w));
634 painter->drawLine(QLineF( x, y+w, x, y-w));
635 painter->drawRect(QRectF(x-w, y-w, mSize, mSize));
635 painter->drawRect(QRectF(x-w, y-w, mSize, mSize));
636 break;
636 break;
637 }
637 }
638 case ssCrossCircle:
638 case ssCrossCircle:
639 {
639 {
640 painter->drawLine(QLineF(x-w*0.707, y-w*0.707, x+w*0.670, y+w*0.670));
640 painter->drawLine(QLineF(x-w*0.707, y-w*0.707, x+w*0.670, y+w*0.670));
641 painter->drawLine(QLineF(x-w*0.707, y+w*0.670, x+w*0.670, y-w*0.707));
641 painter->drawLine(QLineF(x-w*0.707, y+w*0.670, x+w*0.670, y-w*0.707));
642 painter->drawEllipse(QPointF(x, y), w, w);
642 painter->drawEllipse(QPointF(x, y), w, w);
643 break;
643 break;
644 }
644 }
645 case ssPlusCircle:
645 case ssPlusCircle:
646 {
646 {
647 painter->drawLine(QLineF(x-w, y, x+w, y));
647 painter->drawLine(QLineF(x-w, y, x+w, y));
648 painter->drawLine(QLineF( x, y+w, x, y-w));
648 painter->drawLine(QLineF( x, y+w, x, y-w));
649 painter->drawEllipse(QPointF(x, y), w, w);
649 painter->drawEllipse(QPointF(x, y), w, w);
650 break;
650 break;
651 }
651 }
652 case ssPeace:
652 case ssPeace:
653 {
653 {
654 painter->drawLine(QLineF(x, y-w, x, y+w));
654 painter->drawLine(QLineF(x, y-w, x, y+w));
655 painter->drawLine(QLineF(x, y, x-w*0.707, y+w*0.707));
655 painter->drawLine(QLineF(x, y, x-w*0.707, y+w*0.707));
656 painter->drawLine(QLineF(x, y, x+w*0.707, y+w*0.707));
656 painter->drawLine(QLineF(x, y, x+w*0.707, y+w*0.707));
657 painter->drawEllipse(QPointF(x, y), w, w);
657 painter->drawEllipse(QPointF(x, y), w, w);
658 break;
658 break;
659 }
659 }
660 case ssPixmap:
660 case ssPixmap:
661 {
661 {
662 painter->drawPixmap(x-mPixmap.width()*0.5, y-mPixmap.height()*0.5, mPixmap);
662 painter->drawPixmap(x-mPixmap.width()*0.5, y-mPixmap.height()*0.5, mPixmap);
663 break;
663 break;
664 }
664 }
665 case ssCustom:
665 case ssCustom:
666 {
666 {
667 QTransform oldTransform = painter->transform();
667 QTransform oldTransform = painter->transform();
668 painter->translate(x, y);
668 painter->translate(x, y);
669 painter->scale(mSize/6.0, mSize/6.0);
669 painter->scale(mSize/6.0, mSize/6.0);
670 painter->drawPath(mCustomPath);
670 painter->drawPath(mCustomPath);
671 painter->setTransform(oldTransform);
671 painter->setTransform(oldTransform);
672 break;
672 break;
673 }
673 }
674 }
674 }
675 }
675 }
676
676
@@ -748,28 +748,28 void QCPScatterStyle::drawShape(QCPPaint
748 This check is only performed by \ref QCustomPlot::addLayer.
748 This check is only performed by \ref QCustomPlot::addLayer.
749 */
749 */
750 QCPLayer::QCPLayer(QCustomPlot *parentPlot, const QString &layerName) :
750 QCPLayer::QCPLayer(QCustomPlot *parentPlot, const QString &layerName) :
751 QObject(parentPlot),
751 QObject(parentPlot),
752 mParentPlot(parentPlot),
752 mParentPlot(parentPlot),
753 mName(layerName),
753 mName(layerName),
754 mIndex(-1), // will be set to a proper value by the QCustomPlot layer creation function
754 mIndex(-1), // will be set to a proper value by the QCustomPlot layer creation function
755 mVisible(true)
755 mVisible(true)
756 {
756 {
757 // Note: no need to make sure layerName is unique, because layer
757 // Note: no need to make sure layerName is unique, because layer
758 // management is done with QCustomPlot functions.
758 // management is done with QCustomPlot functions.
759 }
759 }
760
760
761 QCPLayer::~QCPLayer()
761 QCPLayer::~QCPLayer()
762 {
762 {
763 // If child layerables are still on this layer, detach them, so they don't try to reach back to this
763 // If child layerables are still on this layer, detach them, so they don't try to reach back to this
764 // then invalid layer once they get deleted/moved themselves. This only happens when layers are deleted
764 // then invalid layer once they get deleted/moved themselves. This only happens when layers are deleted
765 // directly, like in the QCustomPlot destructor. (The regular layer removal procedure for the user is to
765 // directly, like in the QCustomPlot destructor. (The regular layer removal procedure for the user is to
766 // call QCustomPlot::removeLayer, which moves all layerables off this layer before deleting it.)
766 // call QCustomPlot::removeLayer, which moves all layerables off this layer before deleting it.)
767
767
768 while (!mChildren.isEmpty())
768 while (!mChildren.isEmpty())
769 mChildren.last()->setLayer(0); // removes itself from mChildren via removeChild()
769 mChildren.last()->setLayer(0); // removes itself from mChildren via removeChild()
770
770
771 if (mParentPlot->currentLayer() == this)
771 if (mParentPlot->currentLayer() == this)
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.";
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 }
773 }
774
774
775 /*!
775 /*!
@@ -782,7 +782,7 QCPLayer::~QCPLayer()
782 */
782 */
783 void QCPLayer::setVisible(bool visible)
783 void QCPLayer::setVisible(bool visible)
784 {
784 {
785 mVisible = visible;
785 mVisible = visible;
786 }
786 }
787
787
788 /*! \internal
788 /*! \internal
@@ -797,14 +797,14 void QCPLayer::setVisible(bool visible)
797 */
797 */
798 void QCPLayer::addChild(QCPLayerable *layerable, bool prepend)
798 void QCPLayer::addChild(QCPLayerable *layerable, bool prepend)
799 {
799 {
800 if (!mChildren.contains(layerable))
800 if (!mChildren.contains(layerable))
801 {
801 {
802 if (prepend)
802 if (prepend)
803 mChildren.prepend(layerable);
803 mChildren.prepend(layerable);
804 else
804 else
805 mChildren.append(layerable);
805 mChildren.append(layerable);
806 } else
806 } else
807 qDebug() << Q_FUNC_INFO << "layerable is already child of this layer" << reinterpret_cast<quintptr>(layerable);
807 qDebug() << Q_FUNC_INFO << "layerable is already child of this layer" << reinterpret_cast<quintptr>(layerable);
808 }
808 }
809
809
810 /*! \internal
810 /*! \internal
@@ -818,8 +818,8 void QCPLayer::addChild(QCPLayerable *la
818 */
818 */
819 void QCPLayer::removeChild(QCPLayerable *layerable)
819 void QCPLayer::removeChild(QCPLayerable *layerable)
820 {
820 {
821 if (!mChildren.removeOne(layerable))
821 if (!mChildren.removeOne(layerable))
822 qDebug() << Q_FUNC_INFO << "layerable is not child of this layer" << reinterpret_cast<quintptr>(layerable);
822 qDebug() << Q_FUNC_INFO << "layerable is not child of this layer" << reinterpret_cast<quintptr>(layerable);
823 }
823 }
824
824
825
825
@@ -929,28 +929,28 void QCPLayer::removeChild(QCPLayerable
929 not become the QObject-parent (for memory management) of this layerable, \a plot does.
929 not become the QObject-parent (for memory management) of this layerable, \a plot does.
930 */
930 */
931 QCPLayerable::QCPLayerable(QCustomPlot *plot, QString targetLayer, QCPLayerable *parentLayerable) :
931 QCPLayerable::QCPLayerable(QCustomPlot *plot, QString targetLayer, QCPLayerable *parentLayerable) :
932 QObject(plot),
932 QObject(plot),
933 mVisible(true),
933 mVisible(true),
934 mParentPlot(plot),
934 mParentPlot(plot),
935 mParentLayerable(parentLayerable),
935 mParentLayerable(parentLayerable),
936 mLayer(0),
936 mLayer(0),
937 mAntialiased(true)
937 mAntialiased(true)
938 {
938 {
939 if (mParentPlot)
939 if (mParentPlot)
940 {
940 {
941 if (targetLayer.isEmpty())
941 if (targetLayer.isEmpty())
942 setLayer(mParentPlot->currentLayer());
942 setLayer(mParentPlot->currentLayer());
943 else if (!setLayer(targetLayer))
943 else if (!setLayer(targetLayer))
944 qDebug() << Q_FUNC_INFO << "setting QCPlayerable initial layer to" << targetLayer << "failed.";
944 qDebug() << Q_FUNC_INFO << "setting QCPlayerable initial layer to" << targetLayer << "failed.";
945 }
945 }
946 }
946 }
947
947
948 QCPLayerable::~QCPLayerable()
948 QCPLayerable::~QCPLayerable()
949 {
949 {
950 if (mLayer)
950 if (mLayer)
951 {
951 {
952 mLayer->removeChild(this);
952 mLayer->removeChild(this);
953 mLayer = 0;
953 mLayer = 0;
954 }
954 }
955 }
955 }
956
956
@@ -961,7 +961,7 QCPLayerable::~QCPLayerable()
961 */
961 */
962 void QCPLayerable::setVisible(bool on)
962 void QCPLayerable::setVisible(bool on)
963 {
963 {
964 mVisible = on;
964 mVisible = on;
965 }
965 }
966
966
967 /*!
967 /*!
@@ -972,7 +972,7 void QCPLayerable::setVisible(bool on)
972 */
972 */
973 bool QCPLayerable::setLayer(QCPLayer *layer)
973 bool QCPLayerable::setLayer(QCPLayer *layer)
974 {
974 {
975 return moveToLayer(layer, false);
975 return moveToLayer(layer, false);
976 }
976 }
977
977
978 /*! \overload
978 /*! \overload
@@ -982,18 +982,18 bool QCPLayerable::setLayer(QCPLayer *la
982 */
982 */
983 bool QCPLayerable::setLayer(const QString &layerName)
983 bool QCPLayerable::setLayer(const QString &layerName)
984 {
984 {
985 if (!mParentPlot)
985 if (!mParentPlot)
986 {
986 {
987 qDebug() << Q_FUNC_INFO << "no parent QCustomPlot set";
987 qDebug() << Q_FUNC_INFO << "no parent QCustomPlot set";
988 return false;
988 return false;
989 }
989 }
990 if (QCPLayer *layer = mParentPlot->layer(layerName))
990 if (QCPLayer *layer = mParentPlot->layer(layerName))
991 {
991 {
992 return setLayer(layer);
992 return setLayer(layer);
993 } else
993 } else
994 {
994 {
995 qDebug() << Q_FUNC_INFO << "there is no layer with name" << layerName;
995 qDebug() << Q_FUNC_INFO << "there is no layer with name" << layerName;
996 return false;
996 return false;
997 }
997 }
998 }
998 }
999
999
@@ -1005,7 +1005,7 bool QCPLayerable::setLayer(const QStrin
1005 */
1005 */
1006 void QCPLayerable::setAntialiased(bool enabled)
1006 void QCPLayerable::setAntialiased(bool enabled)
1007 {
1007 {
1008 mAntialiased = enabled;
1008 mAntialiased = enabled;
1009 }
1009 }
1010
1010
1011 /*!
1011 /*!
@@ -1023,7 +1023,7 void QCPLayerable::setAntialiased(bool e
1023 */
1023 */
1024 bool QCPLayerable::realVisibility() const
1024 bool QCPLayerable::realVisibility() const
1025 {
1025 {
1026 return mVisible && (!mLayer || mLayer->visible()) && (!mParentLayerable || mParentLayerable.data()->realVisibility());
1026 return mVisible && (!mLayer || mLayer->visible()) && (!mParentLayerable || mParentLayerable.data()->realVisibility());
1027 }
1027 }
1028
1028
1029 /*!
1029 /*!
@@ -1062,10 +1062,10 bool QCPLayerable::realVisibility() cons
1062 */
1062 */
1063 double QCPLayerable::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
1063 double QCPLayerable::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
1064 {
1064 {
1065 Q_UNUSED(pos)
1065 Q_UNUSED(pos)
1066 Q_UNUSED(onlySelectable)
1066 Q_UNUSED(onlySelectable)
1067 Q_UNUSED(details)
1067 Q_UNUSED(details)
1068 return -1.0;
1068 return -1.0;
1069 }
1069 }
1070
1070
1071 /*! \internal
1071 /*! \internal
@@ -1087,17 +1087,17 double QCPLayerable::selectTest(const QP
1087 */
1087 */
1088 void QCPLayerable::initializeParentPlot(QCustomPlot *parentPlot)
1088 void QCPLayerable::initializeParentPlot(QCustomPlot *parentPlot)
1089 {
1089 {
1090 if (mParentPlot)
1090 if (mParentPlot)
1091 {
1091 {
1092 qDebug() << Q_FUNC_INFO << "called with mParentPlot already initialized";
1092 qDebug() << Q_FUNC_INFO << "called with mParentPlot already initialized";
1093 return;
1093 return;
1094 }
1094 }
1095
1095
1096 if (!parentPlot)
1096 if (!parentPlot)
1097 qDebug() << Q_FUNC_INFO << "called with parentPlot zero";
1097 qDebug() << Q_FUNC_INFO << "called with parentPlot zero";
1098
1098
1099 mParentPlot = parentPlot;
1099 mParentPlot = parentPlot;
1100 parentPlotInitialized(mParentPlot);
1100 parentPlotInitialized(mParentPlot);
1101 }
1101 }
1102
1102
1103 /*! \internal
1103 /*! \internal
@@ -1113,7 +1113,7 void QCPLayerable::initializeParentPlot(
1113 */
1113 */
1114 void QCPLayerable::setParentLayerable(QCPLayerable *parentLayerable)
1114 void QCPLayerable::setParentLayerable(QCPLayerable *parentLayerable)
1115 {
1115 {
1116 mParentLayerable = parentLayerable;
1116 mParentLayerable = parentLayerable;
1117 }
1117 }
1118
1118
1119 /*! \internal
1119 /*! \internal
@@ -1126,26 +1126,26 void QCPLayerable::setParentLayerable(QC
1126 */
1126 */
1127 bool QCPLayerable::moveToLayer(QCPLayer *layer, bool prepend)
1127 bool QCPLayerable::moveToLayer(QCPLayer *layer, bool prepend)
1128 {
1128 {
1129 if (layer && !mParentPlot)
1129 if (layer && !mParentPlot)
1130 {
1130 {
1131 qDebug() << Q_FUNC_INFO << "no parent QCustomPlot set";
1131 qDebug() << Q_FUNC_INFO << "no parent QCustomPlot set";
1132 return false;
1132 return false;
1133 }
1133 }
1134 if (layer && layer->parentPlot() != mParentPlot)
1134 if (layer && layer->parentPlot() != mParentPlot)
1135 {
1135 {
1136 qDebug() << Q_FUNC_INFO << "layer" << layer->name() << "is not in same QCustomPlot as this layerable";
1136 qDebug() << Q_FUNC_INFO << "layer" << layer->name() << "is not in same QCustomPlot as this layerable";
1137 return false;
1137 return false;
1138 }
1138 }
1139
1139
1140 QCPLayer *oldLayer = mLayer;
1140 QCPLayer *oldLayer = mLayer;
1141 if (mLayer)
1141 if (mLayer)
1142 mLayer->removeChild(this);
1142 mLayer->removeChild(this);
1143 mLayer = layer;
1143 mLayer = layer;
1144 if (mLayer)
1144 if (mLayer)
1145 mLayer->addChild(this, prepend);
1145 mLayer->addChild(this, prepend);
1146 if (mLayer != oldLayer)
1146 if (mLayer != oldLayer)
1147 emit layerChanged(mLayer);
1147 emit layerChanged(mLayer);
1148 return true;
1148 return true;
1149 }
1149 }
1150
1150
1151 /*! \internal
1151 /*! \internal
@@ -1157,12 +1157,12 bool QCPLayerable::moveToLayer(QCPLayer
1157 */
1157 */
1158 void QCPLayerable::applyAntialiasingHint(QCPPainter *painter, bool localAntialiased, QCP::AntialiasedElement overrideElement) const
1158 void QCPLayerable::applyAntialiasingHint(QCPPainter *painter, bool localAntialiased, QCP::AntialiasedElement overrideElement) const
1159 {
1159 {
1160 if (mParentPlot && mParentPlot->notAntialiasedElements().testFlag(overrideElement))
1160 if (mParentPlot && mParentPlot->notAntialiasedElements().testFlag(overrideElement))
1161 painter->setAntialiasing(false);
1161 painter->setAntialiasing(false);
1162 else if (mParentPlot && mParentPlot->antialiasedElements().testFlag(overrideElement))
1162 else if (mParentPlot && mParentPlot->antialiasedElements().testFlag(overrideElement))
1163 painter->setAntialiasing(true);
1163 painter->setAntialiasing(true);
1164 else
1164 else
1165 painter->setAntialiasing(localAntialiased);
1165 painter->setAntialiasing(localAntialiased);
1166 }
1166 }
1167
1167
1168 /*! \internal
1168 /*! \internal
@@ -1183,7 +1183,7 void QCPLayerable::applyAntialiasingHint
1183 */
1183 */
1184 void QCPLayerable::parentPlotInitialized(QCustomPlot *parentPlot)
1184 void QCPLayerable::parentPlotInitialized(QCustomPlot *parentPlot)
1185 {
1185 {
1186 Q_UNUSED(parentPlot)
1186 Q_UNUSED(parentPlot)
1187 }
1187 }
1188
1188
1189 /*! \internal
1189 /*! \internal
@@ -1199,7 +1199,7 void QCPLayerable::parentPlotInitialized
1199 */
1199 */
1200 QCP::Interaction QCPLayerable::selectionCategory() const
1200 QCP::Interaction QCPLayerable::selectionCategory() const
1201 {
1201 {
1202 return QCP::iSelectOther;
1202 return QCP::iSelectOther;
1203 }
1203 }
1204
1204
1205 /*! \internal
1205 /*! \internal
@@ -1213,10 +1213,10 QCP::Interaction QCPLayerable::selection
1213 */
1213 */
1214 QRect QCPLayerable::clipRect() const
1214 QRect QCPLayerable::clipRect() const
1215 {
1215 {
1216 if (mParentPlot)
1216 if (mParentPlot)
1217 return mParentPlot->viewport();
1217 return mParentPlot->viewport();
1218 else
1218 else
1219 return QRect();
1219 return QRect();
1220 }
1220 }
1221
1221
1222 /*! \internal
1222 /*! \internal
@@ -1249,10 +1249,10 QRect QCPLayerable::clipRect() const
1249 */
1249 */
1250 void QCPLayerable::selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged)
1250 void QCPLayerable::selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged)
1251 {
1251 {
1252 Q_UNUSED(event)
1252 Q_UNUSED(event)
1253 Q_UNUSED(additive)
1253 Q_UNUSED(additive)
1254 Q_UNUSED(details)
1254 Q_UNUSED(details)
1255 Q_UNUSED(selectionStateChanged)
1255 Q_UNUSED(selectionStateChanged)
1256 }
1256 }
1257
1257
1258 /*! \internal
1258 /*! \internal
@@ -1269,7 +1269,7 void QCPLayerable::selectEvent(QMouseEve
1269 */
1269 */
1270 void QCPLayerable::deselectEvent(bool *selectionStateChanged)
1270 void QCPLayerable::deselectEvent(bool *selectionStateChanged)
1271 {
1271 {
1272 Q_UNUSED(selectionStateChanged)
1272 Q_UNUSED(selectionStateChanged)
1273 }
1273 }
1274
1274
1275
1275
@@ -1307,8 +1307,8 const double QCPRange::maxRange = 1e250;
1307 Constructs a range with \a lower and \a upper set to zero.
1307 Constructs a range with \a lower and \a upper set to zero.
1308 */
1308 */
1309 QCPRange::QCPRange() :
1309 QCPRange::QCPRange() :
1310 lower(0),
1310 lower(0),
1311 upper(0)
1311 upper(0)
1312 {
1312 {
1313 }
1313 }
1314
1314
@@ -1316,10 +1316,10 QCPRange::QCPRange() :
1316 Constructs a range with the specified \a lower and \a upper values.
1316 Constructs a range with the specified \a lower and \a upper values.
1317 */
1317 */
1318 QCPRange::QCPRange(double lower, double upper) :
1318 QCPRange::QCPRange(double lower, double upper) :
1319 lower(lower),
1319 lower(lower),
1320 upper(upper)
1320 upper(upper)
1321 {
1321 {
1322 normalize();
1322 normalize();
1323 }
1323 }
1324
1324
1325 /*!
1325 /*!
@@ -1327,7 +1327,7 QCPRange::QCPRange(double lower, double
1327 */
1327 */
1328 double QCPRange::size() const
1328 double QCPRange::size() const
1329 {
1329 {
1330 return upper-lower;
1330 return upper-lower;
1331 }
1331 }
1332
1332
1333 /*!
1333 /*!
@@ -1335,7 +1335,7 double QCPRange::size() const
1335 */
1335 */
1336 double QCPRange::center() const
1336 double QCPRange::center() const
1337 {
1337 {
1338 return (upper+lower)*0.5;
1338 return (upper+lower)*0.5;
1339 }
1339 }
1340
1340
1341 /*!
1341 /*!
@@ -1344,8 +1344,8 double QCPRange::center() const
1344 */
1344 */
1345 void QCPRange::normalize()
1345 void QCPRange::normalize()
1346 {
1346 {
1347 if (lower > upper)
1347 if (lower > upper)
1348 qSwap(lower, upper);
1348 qSwap(lower, upper);
1349 }
1349 }
1350
1350
1351 /*!
1351 /*!
@@ -1358,10 +1358,10 void QCPRange::normalize()
1358 */
1358 */
1359 void QCPRange::expand(const QCPRange &otherRange)
1359 void QCPRange::expand(const QCPRange &otherRange)
1360 {
1360 {
1361 if (lower > otherRange.lower)
1361 if (lower > otherRange.lower)
1362 lower = otherRange.lower;
1362 lower = otherRange.lower;
1363 if (upper < otherRange.upper)
1363 if (upper < otherRange.upper)
1364 upper = otherRange.upper;
1364 upper = otherRange.upper;
1365 }
1365 }
1366
1366
1367
1367
@@ -1373,9 +1373,9 void QCPRange::expand(const QCPRange &ot
1373 */
1373 */
1374 QCPRange QCPRange::expanded(const QCPRange &otherRange) const
1374 QCPRange QCPRange::expanded(const QCPRange &otherRange) const
1375 {
1375 {
1376 QCPRange result = *this;
1376 QCPRange result = *this;
1377 result.expand(otherRange);
1377 result.expand(otherRange);
1378 return result;
1378 return result;
1379 }
1379 }
1380
1380
1381 /*!
1381 /*!
@@ -1392,47 +1392,47 QCPRange QCPRange::expanded(const QCPRan
1392 */
1392 */
1393 QCPRange QCPRange::sanitizedForLogScale() const
1393 QCPRange QCPRange::sanitizedForLogScale() const
1394 {
1394 {
1395 double rangeFac = 1e-3;
1395 double rangeFac = 1e-3;
1396 QCPRange sanitizedRange(lower, upper);
1396 QCPRange sanitizedRange(lower, upper);
1397 sanitizedRange.normalize();
1397 sanitizedRange.normalize();
1398 // can't have range spanning negative and positive values in log plot, so change range to fix it
1398 // can't have range spanning negative and positive values in log plot, so change range to fix it
1399 //if (qFuzzyCompare(sanitizedRange.lower+1, 1) && !qFuzzyCompare(sanitizedRange.upper+1, 1))
1399 //if (qFuzzyCompare(sanitizedRange.lower+1, 1) && !qFuzzyCompare(sanitizedRange.upper+1, 1))
1400 if (sanitizedRange.lower == 0.0 && sanitizedRange.upper != 0.0)
1400 if (sanitizedRange.lower == 0.0 && sanitizedRange.upper != 0.0)
1401 {
1401 {
1402 // case lower is 0
1402 // case lower is 0
1403 if (rangeFac < sanitizedRange.upper*rangeFac)
1403 if (rangeFac < sanitizedRange.upper*rangeFac)
1404 sanitizedRange.lower = rangeFac;
1404 sanitizedRange.lower = rangeFac;
1405 else
1405 else
1406 sanitizedRange.lower = sanitizedRange.upper*rangeFac;
1406 sanitizedRange.lower = sanitizedRange.upper*rangeFac;
1407 } //else if (!qFuzzyCompare(lower+1, 1) && qFuzzyCompare(upper+1, 1))
1407 } //else if (!qFuzzyCompare(lower+1, 1) && qFuzzyCompare(upper+1, 1))
1408 else if (sanitizedRange.lower != 0.0 && sanitizedRange.upper == 0.0)
1408 else if (sanitizedRange.lower != 0.0 && sanitizedRange.upper == 0.0)
1409 {
1409 {
1410 // case upper is 0
1410 // case upper is 0
1411 if (-rangeFac > sanitizedRange.lower*rangeFac)
1411 if (-rangeFac > sanitizedRange.lower*rangeFac)
1412 sanitizedRange.upper = -rangeFac;
1412 sanitizedRange.upper = -rangeFac;
1413 else
1413 else
1414 sanitizedRange.upper = sanitizedRange.lower*rangeFac;
1414 sanitizedRange.upper = sanitizedRange.lower*rangeFac;
1415 } else if (sanitizedRange.lower < 0 && sanitizedRange.upper > 0)
1415 } else if (sanitizedRange.lower < 0 && sanitizedRange.upper > 0)
1416 {
1416 {
1417 // find out whether negative or positive interval is wider to decide which sign domain will be chosen
1417 // find out whether negative or positive interval is wider to decide which sign domain will be chosen
1418 if (-sanitizedRange.lower > sanitizedRange.upper)
1418 if (-sanitizedRange.lower > sanitizedRange.upper)
1419 {
1419 {
1420 // negative is wider, do same as in case upper is 0
1420 // negative is wider, do same as in case upper is 0
1421 if (-rangeFac > sanitizedRange.lower*rangeFac)
1421 if (-rangeFac > sanitizedRange.lower*rangeFac)
1422 sanitizedRange.upper = -rangeFac;
1422 sanitizedRange.upper = -rangeFac;
1423 else
1423 else
1424 sanitizedRange.upper = sanitizedRange.lower*rangeFac;
1424 sanitizedRange.upper = sanitizedRange.lower*rangeFac;
1425 } else
1425 } else
1426 {
1426 {
1427 // positive is wider, do same as in case lower is 0
1427 // positive is wider, do same as in case lower is 0
1428 if (rangeFac < sanitizedRange.upper*rangeFac)
1428 if (rangeFac < sanitizedRange.upper*rangeFac)
1429 sanitizedRange.lower = rangeFac;
1429 sanitizedRange.lower = rangeFac;
1430 else
1430 else
1431 sanitizedRange.lower = sanitizedRange.upper*rangeFac;
1431 sanitizedRange.lower = sanitizedRange.upper*rangeFac;
1432 }
1432 }
1433 }
1433 }
1434 // due to normalization, case lower>0 && upper<0 should never occur, because that implies upper<lower
1434 // due to normalization, case lower>0 && upper<0 should never occur, because that implies upper<lower
1435 return sanitizedRange;
1435 return sanitizedRange;
1436 }
1436 }
1437
1437
1438 /*!
1438 /*!
@@ -1441,9 +1441,9 QCPRange QCPRange::sanitizedForLogScale(
1441 */
1441 */
1442 QCPRange QCPRange::sanitizedForLinScale() const
1442 QCPRange QCPRange::sanitizedForLinScale() const
1443 {
1443 {
1444 QCPRange sanitizedRange(lower, upper);
1444 QCPRange sanitizedRange(lower, upper);
1445 sanitizedRange.normalize();
1445 sanitizedRange.normalize();
1446 return sanitizedRange;
1446 return sanitizedRange;
1447 }
1447 }
1448
1448
1449 /*!
1449 /*!
@@ -1451,7 +1451,7 QCPRange QCPRange::sanitizedForLinScale(
1451 */
1451 */
1452 bool QCPRange::contains(double value) const
1452 bool QCPRange::contains(double value) const
1453 {
1453 {
1454 return value >= lower && value <= upper;
1454 return value >= lower && value <= upper;
1455 }
1455 }
1456
1456
1457 /*!
1457 /*!
@@ -1464,17 +1464,17 bool QCPRange::contains(double value) co
1464 */
1464 */
1465 bool QCPRange::validRange(double lower, double upper)
1465 bool QCPRange::validRange(double lower, double upper)
1466 {
1466 {
1467 /*
1467 /*
1468 return (lower > -maxRange &&
1468 return (lower > -maxRange &&
1469 upper < maxRange &&
1469 upper < maxRange &&
1470 qAbs(lower-upper) > minRange &&
1470 qAbs(lower-upper) > minRange &&
1471 (lower < -minRange || lower > minRange) &&
1471 (lower < -minRange || lower > minRange) &&
1472 (upper < -minRange || upper > minRange));
1472 (upper < -minRange || upper > minRange));
1473 */
1473 */
1474 return (lower > -maxRange &&
1474 return (lower > -maxRange &&
1475 upper < maxRange &&
1475 upper < maxRange &&
1476 qAbs(lower-upper) > minRange &&
1476 qAbs(lower-upper) > minRange &&
1477 qAbs(lower-upper) < maxRange);
1477 qAbs(lower-upper) < maxRange);
1478 }
1478 }
1479
1479
1480 /*!
1480 /*!
@@ -1488,7 +1488,7 bool QCPRange::validRange(double lower,
1488 */
1488 */
1489 bool QCPRange::validRange(const QCPRange &range)
1489 bool QCPRange::validRange(const QCPRange &range)
1490 {
1490 {
1491 /*
1491 /*
1492 return (range.lower > -maxRange &&
1492 return (range.lower > -maxRange &&
1493 range.upper < maxRange &&
1493 range.upper < maxRange &&
1494 qAbs(range.lower-range.upper) > minRange &&
1494 qAbs(range.lower-range.upper) > minRange &&
@@ -1496,10 +1496,10 bool QCPRange::validRange(const QCPRange
1496 (range.lower < -minRange || range.lower > minRange) &&
1496 (range.lower < -minRange || range.lower > minRange) &&
1497 (range.upper < -minRange || range.upper > minRange));
1497 (range.upper < -minRange || range.upper > minRange));
1498 */
1498 */
1499 return (range.lower > -maxRange &&
1499 return (range.lower > -maxRange &&
1500 range.upper < maxRange &&
1500 range.upper < maxRange &&
1501 qAbs(range.lower-range.upper) > minRange &&
1501 qAbs(range.lower-range.upper) > minRange &&
1502 qAbs(range.lower-range.upper) < maxRange);
1502 qAbs(range.lower-range.upper) < maxRange);
1503 }
1503 }
1504
1504
1505
1505
@@ -1557,18 +1557,18 bool QCPRange::validRange(const QCPRange
1557 Creates a new QCPMarginGroup instance in \a parentPlot.
1557 Creates a new QCPMarginGroup instance in \a parentPlot.
1558 */
1558 */
1559 QCPMarginGroup::QCPMarginGroup(QCustomPlot *parentPlot) :
1559 QCPMarginGroup::QCPMarginGroup(QCustomPlot *parentPlot) :
1560 QObject(parentPlot),
1560 QObject(parentPlot),
1561 mParentPlot(parentPlot)
1561 mParentPlot(parentPlot)
1562 {
1562 {
1563 mChildren.insert(QCP::msLeft, QList<QCPLayoutElement*>());
1563 mChildren.insert(QCP::msLeft, QList<QCPLayoutElement*>());
1564 mChildren.insert(QCP::msRight, QList<QCPLayoutElement*>());
1564 mChildren.insert(QCP::msRight, QList<QCPLayoutElement*>());
1565 mChildren.insert(QCP::msTop, QList<QCPLayoutElement*>());
1565 mChildren.insert(QCP::msTop, QList<QCPLayoutElement*>());
1566 mChildren.insert(QCP::msBottom, QList<QCPLayoutElement*>());
1566 mChildren.insert(QCP::msBottom, QList<QCPLayoutElement*>());
1567 }
1567 }
1568
1568
1569 QCPMarginGroup::~QCPMarginGroup()
1569 QCPMarginGroup::~QCPMarginGroup()
1570 {
1570 {
1571 clear();
1571 clear();
1572 }
1572 }
1573
1573
1574 /*!
1574 /*!
@@ -1577,14 +1577,14 QCPMarginGroup::~QCPMarginGroup()
1577 */
1577 */
1578 bool QCPMarginGroup::isEmpty() const
1578 bool QCPMarginGroup::isEmpty() const
1579 {
1579 {
1580 QHashIterator<QCP::MarginSide, QList<QCPLayoutElement*> > it(mChildren);
1580 QHashIterator<QCP::MarginSide, QList<QCPLayoutElement*> > it(mChildren);
1581 while (it.hasNext())
1581 while (it.hasNext())
1582 {
1582 {
1583 it.next();
1583 it.next();
1584 if (!it.value().isEmpty())
1584 if (!it.value().isEmpty())
1585 return false;
1585 return false;
1586 }
1586 }
1587 return true;
1587 return true;
1588 }
1588 }
1589
1589
1590 /*!
1590 /*!
@@ -1593,14 +1593,14 bool QCPMarginGroup::isEmpty() const
1593 */
1593 */
1594 void QCPMarginGroup::clear()
1594 void QCPMarginGroup::clear()
1595 {
1595 {
1596 // make all children remove themselves from this margin group:
1596 // make all children remove themselves from this margin group:
1597 QHashIterator<QCP::MarginSide, QList<QCPLayoutElement*> > it(mChildren);
1597 QHashIterator<QCP::MarginSide, QList<QCPLayoutElement*> > it(mChildren);
1598 while (it.hasNext())
1598 while (it.hasNext())
1599 {
1599 {
1600 it.next();
1600 it.next();
1601 const QList<QCPLayoutElement*> elements = it.value();
1601 const QList<QCPLayoutElement*> elements = it.value();
1602 for (int i=elements.size()-1; i>=0; --i)
1602 for (int i=elements.size()-1; i>=0; --i)
1603 elements.at(i)->setMarginGroup(it.key(), 0); // removes itself from mChildren via removeChild
1603 elements.at(i)->setMarginGroup(it.key(), 0); // removes itself from mChildren via removeChild
1604 }
1604 }
1605 }
1605 }
1606
1606
@@ -1616,18 +1616,18 void QCPMarginGroup::clear()
1616 */
1616 */
1617 int QCPMarginGroup::commonMargin(QCP::MarginSide side) const
1617 int QCPMarginGroup::commonMargin(QCP::MarginSide side) const
1618 {
1618 {
1619 // query all automatic margins of the layout elements in this margin group side and find maximum:
1619 // query all automatic margins of the layout elements in this margin group side and find maximum:
1620 int result = 0;
1620 int result = 0;
1621 const QList<QCPLayoutElement*> elements = mChildren.value(side);
1621 const QList<QCPLayoutElement*> elements = mChildren.value(side);
1622 for (int i=0; i<elements.size(); ++i)
1622 for (int i=0; i<elements.size(); ++i)
1623 {
1623 {
1624 if (!elements.at(i)->autoMargins().testFlag(side))
1624 if (!elements.at(i)->autoMargins().testFlag(side))
1625 continue;
1625 continue;
1626 int m = qMax(elements.at(i)->calculateAutoMargin(side), QCP::getMarginValue(elements.at(i)->minimumMargins(), side));
1626 int m = qMax(elements.at(i)->calculateAutoMargin(side), QCP::getMarginValue(elements.at(i)->minimumMargins(), side));
1627 if (m > result)
1627 if (m > result)
1628 result = m;
1628 result = m;
1629 }
1629 }
1630 return result;
1630 return result;
1631 }
1631 }
1632
1632
1633 /*! \internal
1633 /*! \internal
@@ -1638,10 +1638,10 int QCPMarginGroup::commonMargin(QCP::Ma
1638 */
1638 */
1639 void QCPMarginGroup::addChild(QCP::MarginSide side, QCPLayoutElement *element)
1639 void QCPMarginGroup::addChild(QCP::MarginSide side, QCPLayoutElement *element)
1640 {
1640 {
1641 if (!mChildren[side].contains(element))
1641 if (!mChildren[side].contains(element))
1642 mChildren[side].append(element);
1642 mChildren[side].append(element);
1643 else
1643 else
1644 qDebug() << Q_FUNC_INFO << "element is already child of this margin group side" << reinterpret_cast<quintptr>(element);
1644 qDebug() << Q_FUNC_INFO << "element is already child of this margin group side" << reinterpret_cast<quintptr>(element);
1645 }
1645 }
1646
1646
1647 /*! \internal
1647 /*! \internal
@@ -1652,8 +1652,8 void QCPMarginGroup::addChild(QCP::Margi
1652 */
1652 */
1653 void QCPMarginGroup::removeChild(QCP::MarginSide side, QCPLayoutElement *element)
1653 void QCPMarginGroup::removeChild(QCP::MarginSide side, QCPLayoutElement *element)
1654 {
1654 {
1655 if (!mChildren[side].removeOne(element))
1655 if (!mChildren[side].removeOne(element))
1656 qDebug() << Q_FUNC_INFO << "element is not child of this margin group side" << reinterpret_cast<quintptr>(element);
1656 qDebug() << Q_FUNC_INFO << "element is not child of this margin group side" << reinterpret_cast<quintptr>(element);
1657 }
1657 }
1658
1658
1659
1659
@@ -1742,24 +1742,24 void QCPMarginGroup::removeChild(QCP::Ma
1742 Creates an instance of QCPLayoutElement and sets default values.
1742 Creates an instance of QCPLayoutElement and sets default values.
1743 */
1743 */
1744 QCPLayoutElement::QCPLayoutElement(QCustomPlot *parentPlot) :
1744 QCPLayoutElement::QCPLayoutElement(QCustomPlot *parentPlot) :
1745 QCPLayerable(parentPlot), // parenthood is changed as soon as layout element gets inserted into a layout (except for top level layout)
1745 QCPLayerable(parentPlot), // parenthood is changed as soon as layout element gets inserted into a layout (except for top level layout)
1746 mParentLayout(0),
1746 mParentLayout(0),
1747 mMinimumSize(),
1747 mMinimumSize(),
1748 mMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX),
1748 mMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX),
1749 mRect(0, 0, 0, 0),
1749 mRect(0, 0, 0, 0),
1750 mOuterRect(0, 0, 0, 0),
1750 mOuterRect(0, 0, 0, 0),
1751 mMargins(0, 0, 0, 0),
1751 mMargins(0, 0, 0, 0),
1752 mMinimumMargins(0, 0, 0, 0),
1752 mMinimumMargins(0, 0, 0, 0),
1753 mAutoMargins(QCP::msAll)
1753 mAutoMargins(QCP::msAll)
1754 {
1754 {
1755 }
1755 }
1756
1756
1757 QCPLayoutElement::~QCPLayoutElement()
1757 QCPLayoutElement::~QCPLayoutElement()
1758 {
1758 {
1759 setMarginGroup(QCP::msAll, 0); // unregister at margin groups, if there are any
1759 setMarginGroup(QCP::msAll, 0); // unregister at margin groups, if there are any
1760 // unregister at layout:
1760 // unregister at layout:
1761 if (qobject_cast<QCPLayout*>(mParentLayout)) // the qobject_cast is just a safeguard in case the layout forgets to call clear() in its dtor and this dtor is called by QObject dtor
1761 if (qobject_cast<QCPLayout*>(mParentLayout)) // the qobject_cast is just a safeguard in case the layout forgets to call clear() in its dtor and this dtor is called by QObject dtor
1762 mParentLayout->take(this);
1762 mParentLayout->take(this);
1763 }
1763 }
1764
1764
1765 /*!
1765 /*!
@@ -1775,10 +1775,10 QCPLayoutElement::~QCPLayoutElement()
1775 */
1775 */
1776 void QCPLayoutElement::setOuterRect(const QRect &rect)
1776 void QCPLayoutElement::setOuterRect(const QRect &rect)
1777 {
1777 {
1778 if (mOuterRect != rect)
1778 if (mOuterRect != rect)
1779 {
1779 {
1780 mOuterRect = rect;
1780 mOuterRect = rect;
1781 mRect = mOuterRect.adjusted(mMargins.left(), mMargins.top(), -mMargins.right(), -mMargins.bottom());
1781 mRect = mOuterRect.adjusted(mMargins.left(), mMargins.top(), -mMargins.right(), -mMargins.bottom());
1782 }
1782 }
1783 }
1783 }
1784
1784
@@ -1795,10 +1795,10 void QCPLayoutElement::setOuterRect(cons
1795 */
1795 */
1796 void QCPLayoutElement::setMargins(const QMargins &margins)
1796 void QCPLayoutElement::setMargins(const QMargins &margins)
1797 {
1797 {
1798 if (mMargins != margins)
1798 if (mMargins != margins)
1799 {
1799 {
1800 mMargins = margins;
1800 mMargins = margins;
1801 mRect = mOuterRect.adjusted(mMargins.left(), mMargins.top(), -mMargins.right(), -mMargins.bottom());
1801 mRect = mOuterRect.adjusted(mMargins.left(), mMargins.top(), -mMargins.right(), -mMargins.bottom());
1802 }
1802 }
1803 }
1803 }
1804
1804
@@ -1813,9 +1813,9 void QCPLayoutElement::setMargins(const
1813 */
1813 */
1814 void QCPLayoutElement::setMinimumMargins(const QMargins &margins)
1814 void QCPLayoutElement::setMinimumMargins(const QMargins &margins)
1815 {
1815 {
1816 if (mMinimumMargins != margins)
1816 if (mMinimumMargins != margins)
1817 {
1817 {
1818 mMinimumMargins = margins;
1818 mMinimumMargins = margins;
1819 }
1819 }
1820 }
1820 }
1821
1821
@@ -1831,7 +1831,7 void QCPLayoutElement::setMinimumMargins
1831 */
1831 */
1832 void QCPLayoutElement::setAutoMargins(QCP::MarginSides sides)
1832 void QCPLayoutElement::setAutoMargins(QCP::MarginSides sides)
1833 {
1833 {
1834 mAutoMargins = sides;
1834 mAutoMargins = sides;
1835 }
1835 }
1836
1836
1837 /*!
1837 /*!
@@ -1845,11 +1845,11 void QCPLayoutElement::setAutoMargins(QC
1845 */
1845 */
1846 void QCPLayoutElement::setMinimumSize(const QSize &size)
1846 void QCPLayoutElement::setMinimumSize(const QSize &size)
1847 {
1847 {
1848 if (mMinimumSize != size)
1848 if (mMinimumSize != size)
1849 {
1849 {
1850 mMinimumSize = size;
1850 mMinimumSize = size;
1851 if (mParentLayout)
1851 if (mParentLayout)
1852 mParentLayout->sizeConstraintsChanged();
1852 mParentLayout->sizeConstraintsChanged();
1853 }
1853 }
1854 }
1854 }
1855
1855
@@ -1859,7 +1859,7 void QCPLayoutElement::setMinimumSize(co
1859 */
1859 */
1860 void QCPLayoutElement::setMinimumSize(int width, int height)
1860 void QCPLayoutElement::setMinimumSize(int width, int height)
1861 {
1861 {
1862 setMinimumSize(QSize(width, height));
1862 setMinimumSize(QSize(width, height));
1863 }
1863 }
1864
1864
1865 /*!
1865 /*!
@@ -1868,11 +1868,11 void QCPLayoutElement::setMinimumSize(in
1868 */
1868 */
1869 void QCPLayoutElement::setMaximumSize(const QSize &size)
1869 void QCPLayoutElement::setMaximumSize(const QSize &size)
1870 {
1870 {
1871 if (mMaximumSize != size)
1871 if (mMaximumSize != size)
1872 {
1872 {
1873 mMaximumSize = size;
1873 mMaximumSize = size;
1874 if (mParentLayout)
1874 if (mParentLayout)
1875 mParentLayout->sizeConstraintsChanged();
1875 mParentLayout->sizeConstraintsChanged();
1876 }
1876 }
1877 }
1877 }
1878
1878
@@ -1882,7 +1882,7 void QCPLayoutElement::setMaximumSize(co
1882 */
1882 */
1883 void QCPLayoutElement::setMaximumSize(int width, int height)
1883 void QCPLayoutElement::setMaximumSize(int width, int height)
1884 {
1884 {
1885 setMaximumSize(QSize(width, height));
1885 setMaximumSize(QSize(width, height));
1886 }
1886 }
1887
1887
1888 /*!
1888 /*!
@@ -1898,28 +1898,28 void QCPLayoutElement::setMaximumSize(in
1898 */
1898 */
1899 void QCPLayoutElement::setMarginGroup(QCP::MarginSides sides, QCPMarginGroup *group)
1899 void QCPLayoutElement::setMarginGroup(QCP::MarginSides sides, QCPMarginGroup *group)
1900 {
1900 {
1901 QVector<QCP::MarginSide> sideVector;
1901 QVector<QCP::MarginSide> sideVector;
1902 if (sides.testFlag(QCP::msLeft)) sideVector.append(QCP::msLeft);
1902 if (sides.testFlag(QCP::msLeft)) sideVector.append(QCP::msLeft);
1903 if (sides.testFlag(QCP::msRight)) sideVector.append(QCP::msRight);
1903 if (sides.testFlag(QCP::msRight)) sideVector.append(QCP::msRight);
1904 if (sides.testFlag(QCP::msTop)) sideVector.append(QCP::msTop);
1904 if (sides.testFlag(QCP::msTop)) sideVector.append(QCP::msTop);
1905 if (sides.testFlag(QCP::msBottom)) sideVector.append(QCP::msBottom);
1905 if (sides.testFlag(QCP::msBottom)) sideVector.append(QCP::msBottom);
1906
1906
1907 for (int i=0; i<sideVector.size(); ++i)
1907 for (int i=0; i<sideVector.size(); ++i)
1908 {
1908 {
1909 QCP::MarginSide side = sideVector.at(i);
1909 QCP::MarginSide side = sideVector.at(i);
1910 if (marginGroup(side) != group)
1910 if (marginGroup(side) != group)
1911 {
1911 {
1912 QCPMarginGroup *oldGroup = marginGroup(side);
1912 QCPMarginGroup *oldGroup = marginGroup(side);
1913 if (oldGroup) // unregister at old group
1913 if (oldGroup) // unregister at old group
1914 oldGroup->removeChild(side, this);
1914 oldGroup->removeChild(side, this);
1915
1915
1916 if (!group) // if setting to 0, remove hash entry. Else set hash entry to new group and register there
1916 if (!group) // if setting to 0, remove hash entry. Else set hash entry to new group and register there
1917 {
1917 {
1918 mMarginGroups.remove(side);
1918 mMarginGroups.remove(side);
1919 } else // setting to a new group
1919 } else // setting to a new group
1920 {
1920 {
1921 mMarginGroups[side] = group;
1921 mMarginGroups[side] = group;
1922 group->addChild(side, this);
1922 group->addChild(side, this);
1923 }
1923 }
1924 }
1924 }
1925 }
1925 }
@@ -1939,26 +1939,26 void QCPLayoutElement::setMarginGroup(QC
1939 */
1939 */
1940 void QCPLayoutElement::update(UpdatePhase phase)
1940 void QCPLayoutElement::update(UpdatePhase phase)
1941 {
1941 {
1942 if (phase == upMargins)
1942 if (phase == upMargins)
1943 {
1943 {
1944 if (mAutoMargins != QCP::msNone)
1944 if (mAutoMargins != QCP::msNone)
1945 {
1945 {
1946 // set the margins of this layout element according to automatic margin calculation, either directly or via a margin group:
1946 // set the margins of this layout element according to automatic margin calculation, either directly or via a margin group:
1947 QMargins newMargins = mMargins;
1947 QMargins newMargins = mMargins;
1948 foreach (QCP::MarginSide side, QList<QCP::MarginSide>() << QCP::msLeft << QCP::msRight << QCP::msTop << QCP::msBottom)
1948 foreach (QCP::MarginSide side, QList<QCP::MarginSide>() << QCP::msLeft << QCP::msRight << QCP::msTop << QCP::msBottom)
1949 {
1949 {
1950 if (mAutoMargins.testFlag(side)) // this side's margin shall be calculated automatically
1950 if (mAutoMargins.testFlag(side)) // this side's margin shall be calculated automatically
1951 {
1951 {
1952 if (mMarginGroups.contains(side))
1952 if (mMarginGroups.contains(side))
1953 QCP::setMarginValue(newMargins, side, mMarginGroups[side]->commonMargin(side)); // this side is part of a margin group, so get the margin value from that group
1953 QCP::setMarginValue(newMargins, side, mMarginGroups[side]->commonMargin(side)); // this side is part of a margin group, so get the margin value from that group
1954 else
1954 else
1955 QCP::setMarginValue(newMargins, side, calculateAutoMargin(side)); // this side is not part of a group, so calculate the value directly
1955 QCP::setMarginValue(newMargins, side, calculateAutoMargin(side)); // this side is not part of a group, so calculate the value directly
1956 // apply minimum margin restrictions:
1956 // apply minimum margin restrictions:
1957 if (QCP::getMarginValue(newMargins, side) < QCP::getMarginValue(mMinimumMargins, side))
1957 if (QCP::getMarginValue(newMargins, side) < QCP::getMarginValue(mMinimumMargins, side))
1958 QCP::setMarginValue(newMargins, side, QCP::getMarginValue(mMinimumMargins, side));
1958 QCP::setMarginValue(newMargins, side, QCP::getMarginValue(mMinimumMargins, side));
1959 }
1959 }
1960 }
1960 }
1961 setMargins(newMargins);
1961 setMargins(newMargins);
1962 }
1962 }
1963 }
1963 }
1964 }
1964 }
@@ -1972,7 +1972,7 void QCPLayoutElement::update(UpdatePhas
1972 */
1972 */
1973 QSize QCPLayoutElement::minimumSizeHint() const
1973 QSize QCPLayoutElement::minimumSizeHint() const
1974 {
1974 {
1975 return mMinimumSize;
1975 return mMinimumSize;
1976 }
1976 }
1977
1977
1978 /*!
1978 /*!
@@ -1984,7 +1984,7 QSize QCPLayoutElement::minimumSizeHint(
1984 */
1984 */
1985 QSize QCPLayoutElement::maximumSizeHint() const
1985 QSize QCPLayoutElement::maximumSizeHint() const
1986 {
1986 {
1987 return mMaximumSize;
1987 return mMaximumSize;
1988 }
1988 }
1989
1989
1990 /*!
1990 /*!
@@ -1996,8 +1996,8 QSize QCPLayoutElement::maximumSizeHint(
1996 */
1996 */
1997 QList<QCPLayoutElement*> QCPLayoutElement::elements(bool recursive) const
1997 QList<QCPLayoutElement*> QCPLayoutElement::elements(bool recursive) const
1998 {
1998 {
1999 Q_UNUSED(recursive)
1999 Q_UNUSED(recursive)
2000 return QList<QCPLayoutElement*>();
2000 return QList<QCPLayoutElement*>();
2001 }
2001 }
2002
2002
2003 /*!
2003 /*!
@@ -2013,22 +2013,22 QList<QCPLayoutElement*> QCPLayoutElemen
2013 */
2013 */
2014 double QCPLayoutElement::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
2014 double QCPLayoutElement::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
2015 {
2015 {
2016 Q_UNUSED(details)
2016 Q_UNUSED(details)
2017
2017
2018 if (onlySelectable)
2018 if (onlySelectable)
2019 return -1;
2019 return -1;
2020
2020
2021 if (QRectF(mOuterRect).contains(pos))
2021 if (QRectF(mOuterRect).contains(pos))
2022 {
2022 {
2023 if (mParentPlot)
2023 if (mParentPlot)
2024 return mParentPlot->selectionTolerance()*0.99;
2024 return mParentPlot->selectionTolerance()*0.99;
2025 else
2025 else
2026 {
2026 {
2027 qDebug() << Q_FUNC_INFO << "parent plot not defined";
2027 qDebug() << Q_FUNC_INFO << "parent plot not defined";
2028 return -1;
2028 return -1;
2029 }
2029 }
2030 } else
2030 } else
2031 return -1;
2031 return -1;
2032 }
2032 }
2033
2033
2034 /*! \internal
2034 /*! \internal
@@ -2038,10 +2038,10 double QCPLayoutElement::selectTest(cons
2038 */
2038 */
2039 void QCPLayoutElement::parentPlotInitialized(QCustomPlot *parentPlot)
2039 void QCPLayoutElement::parentPlotInitialized(QCustomPlot *parentPlot)
2040 {
2040 {
2041 foreach (QCPLayoutElement* el, elements(false))
2041 foreach (QCPLayoutElement* el, elements(false))
2042 {
2042 {
2043 if (!el->parentPlot())
2043 if (!el->parentPlot())
2044 el->initializeParentPlot(parentPlot);
2044 el->initializeParentPlot(parentPlot);
2045 }
2045 }
2046 }
2046 }
2047
2047
@@ -2056,7 +2056,7 void QCPLayoutElement::parentPlotInitial
2056 */
2056 */
2057 int QCPLayoutElement::calculateAutoMargin(QCP::MarginSide side)
2057 int QCPLayoutElement::calculateAutoMargin(QCP::MarginSide side)
2058 {
2058 {
2059 return qMax(QCP::getMarginValue(mMargins, side), QCP::getMarginValue(mMinimumMargins, side));
2059 return qMax(QCP::getMarginValue(mMargins, side), QCP::getMarginValue(mMinimumMargins, side));
2060 }
2060 }
2061
2061
2062 ////////////////////////////////////////////////////////////////////////////////////////////////////
2062 ////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -2150,40 +2150,40 QCPLayout::QCPLayout()
2150 */
2150 */
2151 void QCPLayout::update(UpdatePhase phase)
2151 void QCPLayout::update(UpdatePhase phase)
2152 {
2152 {
2153 QCPLayoutElement::update(phase);
2153 QCPLayoutElement::update(phase);
2154
2154
2155 // set child element rects according to layout:
2155 // set child element rects according to layout:
2156 if (phase == upLayout)
2156 if (phase == upLayout)
2157 updateLayout();
2157 updateLayout();
2158
2158
2159 // propagate update call to child elements:
2159 // propagate update call to child elements:
2160 const int elCount = elementCount();
2160 const int elCount = elementCount();
2161 for (int i=0; i<elCount; ++i)
2161 for (int i=0; i<elCount; ++i)
2162 {
2162 {
2163 if (QCPLayoutElement *el = elementAt(i))
2163 if (QCPLayoutElement *el = elementAt(i))
2164 el->update(phase);
2164 el->update(phase);
2165 }
2165 }
2166 }
2166 }
2167
2167
2168 /* inherits documentation from base class */
2168 /* inherits documentation from base class */
2169 QList<QCPLayoutElement*> QCPLayout::elements(bool recursive) const
2169 QList<QCPLayoutElement*> QCPLayout::elements(bool recursive) const
2170 {
2170 {
2171 const int c = elementCount();
2171 const int c = elementCount();
2172 QList<QCPLayoutElement*> result;
2172 QList<QCPLayoutElement*> result;
2173 #if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
2173 #if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
2174 result.reserve(c);
2174 result.reserve(c);
2175 #endif
2175 #endif
2176 for (int i=0; i<c; ++i)
2176 for (int i=0; i<c; ++i)
2177 result.append(elementAt(i));
2177 result.append(elementAt(i));
2178 if (recursive)
2178 if (recursive)
2179 {
2179 {
2180 for (int i=0; i<c; ++i)
2180 for (int i=0; i<c; ++i)
2181 {
2181 {
2182 if (result.at(i))
2182 if (result.at(i))
2183 result << result.at(i)->elements(recursive);
2183 result << result.at(i)->elements(recursive);
2184 }
2184 }
2185 }
2185 }
2186 return result;
2186 return result;
2187 }
2187 }
2188
2188
2189 /*!
2189 /*!
@@ -2208,12 +2208,12 void QCPLayout::simplify()
2208 */
2208 */
2209 bool QCPLayout::removeAt(int index)
2209 bool QCPLayout::removeAt(int index)
2210 {
2210 {
2211 if (QCPLayoutElement *el = takeAt(index))
2211 if (QCPLayoutElement *el = takeAt(index))
2212 {
2212 {
2213 delete el;
2213 delete el;
2214 return true;
2214 return true;
2215 } else
2215 } else
2216 return false;
2216 return false;
2217 }
2217 }
2218
2218
2219 /*!
2219 /*!
@@ -2227,12 +2227,12 bool QCPLayout::removeAt(int index)
2227 */
2227 */
2228 bool QCPLayout::remove(QCPLayoutElement *element)
2228 bool QCPLayout::remove(QCPLayoutElement *element)
2229 {
2229 {
2230 if (take(element))
2230 if (take(element))
2231 {
2231 {
2232 delete element;
2232 delete element;
2233 return true;
2233 return true;
2234 } else
2234 } else
2235 return false;
2235 return false;
2236 }
2236 }
2237
2237
2238 /*!
2238 /*!
@@ -2242,12 +2242,12 bool QCPLayout::remove(QCPLayoutElement
2242 */
2242 */
2243 void QCPLayout::clear()
2243 void QCPLayout::clear()
2244 {
2244 {
2245 for (int i=elementCount()-1; i>=0; --i)
2245 for (int i=elementCount()-1; i>=0; --i)
2246 {
2246 {
2247 if (elementAt(i))
2247 if (elementAt(i))
2248 removeAt(i);
2248 removeAt(i);
2249 }
2249 }
2250 simplify();
2250 simplify();
2251 }
2251 }
2252
2252
2253 /*!
2253 /*!
@@ -2260,10 +2260,10 void QCPLayout::clear()
2260 */
2260 */
2261 void QCPLayout::sizeConstraintsChanged() const
2261 void QCPLayout::sizeConstraintsChanged() const
2262 {
2262 {
2263 if (QWidget *w = qobject_cast<QWidget*>(parent()))
2263 if (QWidget *w = qobject_cast<QWidget*>(parent()))
2264 w->updateGeometry();
2264 w->updateGeometry();
2265 else if (QCPLayout *l = qobject_cast<QCPLayout*>(parent()))
2265 else if (QCPLayout *l = qobject_cast<QCPLayout*>(parent()))
2266 l->sizeConstraintsChanged();
2266 l->sizeConstraintsChanged();
2267 }
2267 }
2268
2268
2269 /*! \internal
2269 /*! \internal
@@ -2297,15 +2297,15 void QCPLayout::updateLayout()
2297 */
2297 */
2298 void QCPLayout::adoptElement(QCPLayoutElement *el)
2298 void QCPLayout::adoptElement(QCPLayoutElement *el)
2299 {
2299 {
2300 if (el)
2300 if (el)
2301 {
2301 {
2302 el->mParentLayout = this;
2302 el->mParentLayout = this;
2303 el->setParentLayerable(this);
2303 el->setParentLayerable(this);
2304 el->setParent(this);
2304 el->setParent(this);
2305 if (!el->parentPlot())
2305 if (!el->parentPlot())
2306 el->initializeParentPlot(mParentPlot);
2306 el->initializeParentPlot(mParentPlot);
2307 } else
2307 } else
2308 qDebug() << Q_FUNC_INFO << "Null element passed";
2308 qDebug() << Q_FUNC_INFO << "Null element passed";
2309 }
2309 }
2310
2310
2311 /*! \internal
2311 /*! \internal
@@ -2320,14 +2320,14 void QCPLayout::adoptElement(QCPLayoutEl
2320 */
2320 */
2321 void QCPLayout::releaseElement(QCPLayoutElement *el)
2321 void QCPLayout::releaseElement(QCPLayoutElement *el)
2322 {
2322 {
2323 if (el)
2323 if (el)
2324 {
2324 {
2325 el->mParentLayout = 0;
2325 el->mParentLayout = 0;
2326 el->setParentLayerable(0);
2326 el->setParentLayerable(0);
2327 el->setParent(mParentPlot);
2327 el->setParent(mParentPlot);
2328 // Note: Don't initializeParentPlot(0) here, because layout element will stay in same parent plot
2328 // Note: Don't initializeParentPlot(0) here, because layout element will stay in same parent plot
2329 } else
2329 } else
2330 qDebug() << Q_FUNC_INFO << "Null element passed";
2330 qDebug() << Q_FUNC_INFO << "Null element passed";
2331 }
2331 }
2332
2332
2333 /*! \internal
2333 /*! \internal
@@ -2361,115 +2361,115 void QCPLayout::releaseElement(QCPLayout
2361 */
2361 */
2362 QVector<int> QCPLayout::getSectionSizes(QVector<int> maxSizes, QVector<int> minSizes, QVector<double> stretchFactors, int totalSize) const
2362 QVector<int> QCPLayout::getSectionSizes(QVector<int> maxSizes, QVector<int> minSizes, QVector<double> stretchFactors, int totalSize) const
2363 {
2363 {
2364 if (maxSizes.size() != minSizes.size() || minSizes.size() != stretchFactors.size())
2364 if (maxSizes.size() != minSizes.size() || minSizes.size() != stretchFactors.size())
2365 {
2365 {
2366 qDebug() << Q_FUNC_INFO << "Passed vector sizes aren't equal:" << maxSizes << minSizes << stretchFactors;
2366 qDebug() << Q_FUNC_INFO << "Passed vector sizes aren't equal:" << maxSizes << minSizes << stretchFactors;
2367 return QVector<int>();
2367 return QVector<int>();
2368 }
2368 }
2369 if (stretchFactors.isEmpty())
2369 if (stretchFactors.isEmpty())
2370 return QVector<int>();
2370 return QVector<int>();
2371 int sectionCount = stretchFactors.size();
2371 int sectionCount = stretchFactors.size();
2372 QVector<double> sectionSizes(sectionCount);
2372 QVector<double> sectionSizes(sectionCount);
2373 // if provided total size is forced smaller than total minimum size, ignore minimum sizes (squeeze sections):
2373 // if provided total size is forced smaller than total minimum size, ignore minimum sizes (squeeze sections):
2374 int minSizeSum = 0;
2374 int minSizeSum = 0;
2375 for (int i=0; i<sectionCount; ++i)
2375 for (int i=0; i<sectionCount; ++i)
2376 minSizeSum += minSizes.at(i);
2376 minSizeSum += minSizes.at(i);
2377 if (totalSize < minSizeSum)
2377 if (totalSize < minSizeSum)
2378 {
2378 {
2379 // new stretch factors are minimum sizes and minimum sizes are set to zero:
2379 // new stretch factors are minimum sizes and minimum sizes are set to zero:
2380 for (int i=0; i<sectionCount; ++i)
2380 for (int i=0; i<sectionCount; ++i)
2381 {
2381 {
2382 stretchFactors[i] = minSizes.at(i);
2382 stretchFactors[i] = minSizes.at(i);
2383 minSizes[i] = 0;
2383 minSizes[i] = 0;
2384 }
2384 }
2385 }
2385 }
2386
2386
2387 QList<int> minimumLockedSections;
2387 QList<int> minimumLockedSections;
2388 QList<int> unfinishedSections;
2388 QList<int> unfinishedSections;
2389 for (int i=0; i<sectionCount; ++i)
2389 for (int i=0; i<sectionCount; ++i)
2390 unfinishedSections.append(i);
2390 unfinishedSections.append(i);
2391 double freeSize = totalSize;
2391 double freeSize = totalSize;
2392
2392
2393 int outerIterations = 0;
2393 int outerIterations = 0;
2394 while (!unfinishedSections.isEmpty() && outerIterations < sectionCount*2) // the iteration check ist just a failsafe in case something really strange happens
2394 while (!unfinishedSections.isEmpty() && outerIterations < sectionCount*2) // the iteration check ist just a failsafe in case something really strange happens
2395 {
2395 {
2396 ++outerIterations;
2396 ++outerIterations;
2397 int innerIterations = 0;
2397 int innerIterations = 0;
2398 while (!unfinishedSections.isEmpty() && innerIterations < sectionCount*2) // the iteration check ist just a failsafe in case something really strange happens
2398 while (!unfinishedSections.isEmpty() && innerIterations < sectionCount*2) // the iteration check ist just a failsafe in case something really strange happens
2399 {
2399 {
2400 ++innerIterations;
2400 ++innerIterations;
2401 // find section that hits its maximum next:
2401 // find section that hits its maximum next:
2402 int nextId = -1;
2402 int nextId = -1;
2403 double nextMax = 1e12;
2403 double nextMax = 1e12;
2404 for (int i=0; i<unfinishedSections.size(); ++i)
2404 for (int i=0; i<unfinishedSections.size(); ++i)
2405 {
2405 {
2406 int secId = unfinishedSections.at(i);
2406 int secId = unfinishedSections.at(i);
2407 double hitsMaxAt = (maxSizes.at(secId)-sectionSizes.at(secId))/stretchFactors.at(secId);
2407 double hitsMaxAt = (maxSizes.at(secId)-sectionSizes.at(secId))/stretchFactors.at(secId);
2408 if (hitsMaxAt < nextMax)
2408 if (hitsMaxAt < nextMax)
2409 {
2409 {
2410 nextMax = hitsMaxAt;
2410 nextMax = hitsMaxAt;
2411 nextId = secId;
2411 nextId = secId;
2412 }
2412 }
2413 }
2413 }
2414 // check if that maximum is actually within the bounds of the total size (i.e. can we stretch all remaining sections so far that the found section
2414 // check if that maximum is actually within the bounds of the total size (i.e. can we stretch all remaining sections so far that the found section
2415 // actually hits its maximum, without exceeding the total size when we add up all sections)
2415 // actually hits its maximum, without exceeding the total size when we add up all sections)
2416 double stretchFactorSum = 0;
2416 double stretchFactorSum = 0;
2417 for (int i=0; i<unfinishedSections.size(); ++i)
2417 for (int i=0; i<unfinishedSections.size(); ++i)
2418 stretchFactorSum += stretchFactors.at(unfinishedSections.at(i));
2418 stretchFactorSum += stretchFactors.at(unfinishedSections.at(i));
2419 double nextMaxLimit = freeSize/stretchFactorSum;
2419 double nextMaxLimit = freeSize/stretchFactorSum;
2420 if (nextMax < nextMaxLimit) // next maximum is actually hit, move forward to that point and fix the size of that section
2420 if (nextMax < nextMaxLimit) // next maximum is actually hit, move forward to that point and fix the size of that section
2421 {
2421 {
2422 for (int i=0; i<unfinishedSections.size(); ++i)
2422 for (int i=0; i<unfinishedSections.size(); ++i)
2423 {
2423 {
2424 sectionSizes[unfinishedSections.at(i)] += nextMax*stretchFactors.at(unfinishedSections.at(i)); // increment all sections
2424 sectionSizes[unfinishedSections.at(i)] += nextMax*stretchFactors.at(unfinishedSections.at(i)); // increment all sections
2425 freeSize -= nextMax*stretchFactors.at(unfinishedSections.at(i));
2425 freeSize -= nextMax*stretchFactors.at(unfinishedSections.at(i));
2426 }
2426 }
2427 unfinishedSections.removeOne(nextId); // exclude the section that is now at maximum from further changes
2427 unfinishedSections.removeOne(nextId); // exclude the section that is now at maximum from further changes
2428 } else // next maximum isn't hit, just distribute rest of free space on remaining sections
2428 } else // next maximum isn't hit, just distribute rest of free space on remaining sections
2429 {
2429 {
2430 for (int i=0; i<unfinishedSections.size(); ++i)
2430 for (int i=0; i<unfinishedSections.size(); ++i)
2431 sectionSizes[unfinishedSections.at(i)] += nextMaxLimit*stretchFactors.at(unfinishedSections.at(i)); // increment all sections
2431 sectionSizes[unfinishedSections.at(i)] += nextMaxLimit*stretchFactors.at(unfinishedSections.at(i)); // increment all sections
2432 unfinishedSections.clear();
2432 unfinishedSections.clear();
2433 }
2433 }
2434 }
2434 }
2435 if (innerIterations == sectionCount*2)
2435 if (innerIterations == sectionCount*2)
2436 qDebug() << Q_FUNC_INFO << "Exceeded maximum expected inner iteration count, layouting aborted. Input was:" << maxSizes << minSizes << stretchFactors << totalSize;
2436 qDebug() << Q_FUNC_INFO << "Exceeded maximum expected inner iteration count, layouting aborted. Input was:" << maxSizes << minSizes << stretchFactors << totalSize;
2437
2437
2438 // now check whether the resulting section sizes violate minimum restrictions:
2438 // now check whether the resulting section sizes violate minimum restrictions:
2439 bool foundMinimumViolation = false;
2439 bool foundMinimumViolation = false;
2440 for (int i=0; i<sectionSizes.size(); ++i)
2440 for (int i=0; i<sectionSizes.size(); ++i)
2441 {
2441 {
2442 if (minimumLockedSections.contains(i))
2442 if (minimumLockedSections.contains(i))
2443 continue;
2443 continue;
2444 if (sectionSizes.at(i) < minSizes.at(i)) // section violates minimum
2444 if (sectionSizes.at(i) < minSizes.at(i)) // section violates minimum
2445 {
2445 {
2446 sectionSizes[i] = minSizes.at(i); // set it to minimum
2446 sectionSizes[i] = minSizes.at(i); // set it to minimum
2447 foundMinimumViolation = true; // make sure we repeat the whole optimization process
2447 foundMinimumViolation = true; // make sure we repeat the whole optimization process
2448 minimumLockedSections.append(i);
2448 minimumLockedSections.append(i);
2449 }
2449 }
2450 }
2450 }
2451 if (foundMinimumViolation)
2451 if (foundMinimumViolation)
2452 {
2452 {
2453 freeSize = totalSize;
2453 freeSize = totalSize;
2454 for (int i=0; i<sectionCount; ++i)
2454 for (int i=0; i<sectionCount; ++i)
2455 {
2455 {
2456 if (!minimumLockedSections.contains(i)) // only put sections that haven't hit their minimum back into the pool
2456 if (!minimumLockedSections.contains(i)) // only put sections that haven't hit their minimum back into the pool
2457 unfinishedSections.append(i);
2457 unfinishedSections.append(i);
2458 else
2458 else
2459 freeSize -= sectionSizes.at(i); // remove size of minimum locked sections from available space in next round
2459 freeSize -= sectionSizes.at(i); // remove size of minimum locked sections from available space in next round
2460 }
2460 }
2461 // reset all section sizes to zero that are in unfinished sections (all others have been set to their minimum):
2461 // reset all section sizes to zero that are in unfinished sections (all others have been set to their minimum):
2462 for (int i=0; i<unfinishedSections.size(); ++i)
2462 for (int i=0; i<unfinishedSections.size(); ++i)
2463 sectionSizes[unfinishedSections.at(i)] = 0;
2463 sectionSizes[unfinishedSections.at(i)] = 0;
2464 }
2464 }
2465 }
2465 }
2466 if (outerIterations == sectionCount*2)
2466 if (outerIterations == sectionCount*2)
2467 qDebug() << Q_FUNC_INFO << "Exceeded maximum expected outer iteration count, layouting aborted. Input was:" << maxSizes << minSizes << stretchFactors << totalSize;
2467 qDebug() << Q_FUNC_INFO << "Exceeded maximum expected outer iteration count, layouting aborted. Input was:" << maxSizes << minSizes << stretchFactors << totalSize;
2468
2468
2469 QVector<int> result(sectionCount);
2469 QVector<int> result(sectionCount);
2470 for (int i=0; i<sectionCount; ++i)
2470 for (int i=0; i<sectionCount; ++i)
2471 result[i] = qRound(sectionSizes.at(i));
2471 result[i] = qRound(sectionSizes.at(i));
2472 return result;
2472 return result;
2473 }
2473 }
2474
2474
2475
2475
@@ -2497,16 +2497,16 QVector<int> QCPLayout::getSectionSizes(
2497 Creates an instance of QCPLayoutGrid and sets default values.
2497 Creates an instance of QCPLayoutGrid and sets default values.
2498 */
2498 */
2499 QCPLayoutGrid::QCPLayoutGrid() :
2499 QCPLayoutGrid::QCPLayoutGrid() :
2500 mColumnSpacing(5),
2500 mColumnSpacing(5),
2501 mRowSpacing(5)
2501 mRowSpacing(5)
2502 {
2502 {
2503 }
2503 }
2504
2504
2505 QCPLayoutGrid::~QCPLayoutGrid()
2505 QCPLayoutGrid::~QCPLayoutGrid()
2506 {
2506 {
2507 // clear all child layout elements. This is important because only the specific layouts know how
2507 // clear all child layout elements. This is important because only the specific layouts know how
2508 // to handle removing elements (clear calls virtual removeAt method to do that).
2508 // to handle removing elements (clear calls virtual removeAt method to do that).
2509 clear();
2509 clear();
2510 }
2510 }
2511
2511
2512 /*!
2512 /*!
@@ -2519,19 +2519,19 QCPLayoutGrid::~QCPLayoutGrid()
2519 */
2519 */
2520 QCPLayoutElement *QCPLayoutGrid::element(int row, int column) const
2520 QCPLayoutElement *QCPLayoutGrid::element(int row, int column) const
2521 {
2521 {
2522 if (row >= 0 && row < mElements.size())
2522 if (row >= 0 && row < mElements.size())
2523 {
2523 {
2524 if (column >= 0 && column < mElements.first().size())
2524 if (column >= 0 && column < mElements.first().size())
2525 {
2525 {
2526 if (QCPLayoutElement *result = mElements.at(row).at(column))
2526 if (QCPLayoutElement *result = mElements.at(row).at(column))
2527 return result;
2527 return result;
2528 else
2528 else
2529 qDebug() << Q_FUNC_INFO << "Requested cell is empty. Row:" << row << "Column:" << column;
2529 qDebug() << Q_FUNC_INFO << "Requested cell is empty. Row:" << row << "Column:" << column;
2530 } else
2530 } else
2531 qDebug() << Q_FUNC_INFO << "Invalid column. Row:" << row << "Column:" << column;
2531 qDebug() << Q_FUNC_INFO << "Invalid column. Row:" << row << "Column:" << column;
2532 } else
2532 } else
2533 qDebug() << Q_FUNC_INFO << "Invalid row. Row:" << row << "Column:" << column;
2533 qDebug() << Q_FUNC_INFO << "Invalid row. Row:" << row << "Column:" << column;
2534 return 0;
2534 return 0;
2535 }
2535 }
2536
2536
2537 /*!
2537 /*!
@@ -2541,7 +2541,7 QCPLayoutElement *QCPLayoutGrid::element
2541 */
2541 */
2542 int QCPLayoutGrid::rowCount() const
2542 int QCPLayoutGrid::rowCount() const
2543 {
2543 {
2544 return mElements.size();
2544 return mElements.size();
2545 }
2545 }
2546
2546
2547 /*!
2547 /*!
@@ -2551,10 +2551,10 int QCPLayoutGrid::rowCount() const
2551 */
2551 */
2552 int QCPLayoutGrid::columnCount() const
2552 int QCPLayoutGrid::columnCount() const
2553 {
2553 {
2554 if (mElements.size() > 0)
2554 if (mElements.size() > 0)
2555 return mElements.first().size();
2555 return mElements.first().size();
2556 else
2556 else
2557 return 0;
2557 return 0;
2558 }
2558 }
2559
2559
2560 /*!
2560 /*!
@@ -2569,21 +2569,21 int QCPLayoutGrid::columnCount() const
2569 */
2569 */
2570 bool QCPLayoutGrid::addElement(int row, int column, QCPLayoutElement *element)
2570 bool QCPLayoutGrid::addElement(int row, int column, QCPLayoutElement *element)
2571 {
2571 {
2572 if (element)
2572 if (element)
2573 {
2573 {
2574 if (!hasElement(row, column))
2574 if (!hasElement(row, column))
2575 {
2575 {
2576 if (element->layout()) // remove from old layout first
2576 if (element->layout()) // remove from old layout first
2577 element->layout()->take(element);
2577 element->layout()->take(element);
2578 expandTo(row+1, column+1);
2578 expandTo(row+1, column+1);
2579 mElements[row][column] = element;
2579 mElements[row][column] = element;
2580 adoptElement(element);
2580 adoptElement(element);
2581 return true;
2581 return true;
2582 } else
2582 } else
2583 qDebug() << Q_FUNC_INFO << "There is already an element in the specified row/column:" << row << column;
2583 qDebug() << Q_FUNC_INFO << "There is already an element in the specified row/column:" << row << column;
2584 } else
2584 } else
2585 qDebug() << Q_FUNC_INFO << "Can't add null element to row/column:" << row << column;
2585 qDebug() << Q_FUNC_INFO << "Can't add null element to row/column:" << row << column;
2586 return false;
2586 return false;
2587 }
2587 }
2588
2588
2589 /*!
2589 /*!
@@ -2594,10 +2594,10 bool QCPLayoutGrid::addElement(int row,
2594 */
2594 */
2595 bool QCPLayoutGrid::hasElement(int row, int column)
2595 bool QCPLayoutGrid::hasElement(int row, int column)
2596 {
2596 {
2597 if (row >= 0 && row < rowCount() && column >= 0 && column < columnCount())
2597 if (row >= 0 && row < rowCount() && column >= 0 && column < columnCount())
2598 return mElements.at(row).at(column);
2598 return mElements.at(row).at(column);
2599 else
2599 else
2600 return false;
2600 return false;
2601 }
2601 }
2602
2602
2603 /*!
2603 /*!
@@ -2613,14 +2613,14 bool QCPLayoutGrid::hasElement(int row,
2613 */
2613 */
2614 void QCPLayoutGrid::setColumnStretchFactor(int column, double factor)
2614 void QCPLayoutGrid::setColumnStretchFactor(int column, double factor)
2615 {
2615 {
2616 if (column >= 0 && column < columnCount())
2616 if (column >= 0 && column < columnCount())
2617 {
2617 {
2618 if (factor > 0)
2618 if (factor > 0)
2619 mColumnStretchFactors[column] = factor;
2619 mColumnStretchFactors[column] = factor;
2620 else
2620 else
2621 qDebug() << Q_FUNC_INFO << "Invalid stretch factor, must be positive:" << factor;
2621 qDebug() << Q_FUNC_INFO << "Invalid stretch factor, must be positive:" << factor;
2622 } else
2622 } else
2623 qDebug() << Q_FUNC_INFO << "Invalid column:" << column;
2623 qDebug() << Q_FUNC_INFO << "Invalid column:" << column;
2624 }
2624 }
2625
2625
2626 /*!
2626 /*!
@@ -2636,19 +2636,19 void QCPLayoutGrid::setColumnStretchFact
2636 */
2636 */
2637 void QCPLayoutGrid::setColumnStretchFactors(const QList<double> &factors)
2637 void QCPLayoutGrid::setColumnStretchFactors(const QList<double> &factors)
2638 {
2638 {
2639 if (factors.size() == mColumnStretchFactors.size())
2639 if (factors.size() == mColumnStretchFactors.size())
2640 {
2640 {
2641 mColumnStretchFactors = factors;
2641 mColumnStretchFactors = factors;
2642 for (int i=0; i<mColumnStretchFactors.size(); ++i)
2642 for (int i=0; i<mColumnStretchFactors.size(); ++i)
2643 {
2643 {
2644 if (mColumnStretchFactors.at(i) <= 0)
2644 if (mColumnStretchFactors.at(i) <= 0)
2645 {
2645 {
2646 qDebug() << Q_FUNC_INFO << "Invalid stretch factor, must be positive:" << mColumnStretchFactors.at(i);
2646 qDebug() << Q_FUNC_INFO << "Invalid stretch factor, must be positive:" << mColumnStretchFactors.at(i);
2647 mColumnStretchFactors[i] = 1;
2647 mColumnStretchFactors[i] = 1;
2648 }
2648 }
2649 }
2649 }
2650 } else
2650 } else
2651 qDebug() << Q_FUNC_INFO << "Column count not equal to passed stretch factor count:" << factors;
2651 qDebug() << Q_FUNC_INFO << "Column count not equal to passed stretch factor count:" << factors;
2652 }
2652 }
2653
2653
2654 /*!
2654 /*!
@@ -2664,14 +2664,14 void QCPLayoutGrid::setColumnStretchFact
2664 */
2664 */
2665 void QCPLayoutGrid::setRowStretchFactor(int row, double factor)
2665 void QCPLayoutGrid::setRowStretchFactor(int row, double factor)
2666 {
2666 {
2667 if (row >= 0 && row < rowCount())
2667 if (row >= 0 && row < rowCount())
2668 {
2668 {
2669 if (factor > 0)
2669 if (factor > 0)
2670 mRowStretchFactors[row] = factor;
2670 mRowStretchFactors[row] = factor;
2671 else
2671 else
2672 qDebug() << Q_FUNC_INFO << "Invalid stretch factor, must be positive:" << factor;
2672 qDebug() << Q_FUNC_INFO << "Invalid stretch factor, must be positive:" << factor;
2673 } else
2673 } else
2674 qDebug() << Q_FUNC_INFO << "Invalid row:" << row;
2674 qDebug() << Q_FUNC_INFO << "Invalid row:" << row;
2675 }
2675 }
2676
2676
2677 /*!
2677 /*!
@@ -2687,19 +2687,19 void QCPLayoutGrid::setRowStretchFactor(
2687 */
2687 */
2688 void QCPLayoutGrid::setRowStretchFactors(const QList<double> &factors)
2688 void QCPLayoutGrid::setRowStretchFactors(const QList<double> &factors)
2689 {
2689 {
2690 if (factors.size() == mRowStretchFactors.size())
2690 if (factors.size() == mRowStretchFactors.size())
2691 {
2691 {
2692 mRowStretchFactors = factors;
2692 mRowStretchFactors = factors;
2693 for (int i=0; i<mRowStretchFactors.size(); ++i)
2693 for (int i=0; i<mRowStretchFactors.size(); ++i)
2694 {
2694 {
2695 if (mRowStretchFactors.at(i) <= 0)
2695 if (mRowStretchFactors.at(i) <= 0)
2696 {
2696 {
2697 qDebug() << Q_FUNC_INFO << "Invalid stretch factor, must be positive:" << mRowStretchFactors.at(i);
2697 qDebug() << Q_FUNC_INFO << "Invalid stretch factor, must be positive:" << mRowStretchFactors.at(i);
2698 mRowStretchFactors[i] = 1;
2698 mRowStretchFactors[i] = 1;
2699 }
2699 }
2700 }
2700 }
2701 } else
2701 } else
2702 qDebug() << Q_FUNC_INFO << "Row count not equal to passed stretch factor count:" << factors;
2702 qDebug() << Q_FUNC_INFO << "Row count not equal to passed stretch factor count:" << factors;
2703 }
2703 }
2704
2704
2705 /*!
2705 /*!
@@ -2709,7 +2709,7 void QCPLayoutGrid::setRowStretchFactors
2709 */
2709 */
2710 void QCPLayoutGrid::setColumnSpacing(int pixels)
2710 void QCPLayoutGrid::setColumnSpacing(int pixels)
2711 {
2711 {
2712 mColumnSpacing = pixels;
2712 mColumnSpacing = pixels;
2713 }
2713 }
2714
2714
2715 /*!
2715 /*!
@@ -2719,7 +2719,7 void QCPLayoutGrid::setColumnSpacing(int
2719 */
2719 */
2720 void QCPLayoutGrid::setRowSpacing(int pixels)
2720 void QCPLayoutGrid::setRowSpacing(int pixels)
2721 {
2721 {
2722 mRowSpacing = pixels;
2722 mRowSpacing = pixels;
2723 }
2723 }
2724
2724
2725 /*!
2725 /*!
@@ -2738,21 +2738,21 void QCPLayoutGrid::setRowSpacing(int pi
2738 */
2738 */
2739 void QCPLayoutGrid::expandTo(int newRowCount, int newColumnCount)
2739 void QCPLayoutGrid::expandTo(int newRowCount, int newColumnCount)
2740 {
2740 {
2741 // add rows as necessary:
2741 // add rows as necessary:
2742 while (rowCount() < newRowCount)
2742 while (rowCount() < newRowCount)
2743 {
2743 {
2744 mElements.append(QList<QCPLayoutElement*>());
2744 mElements.append(QList<QCPLayoutElement*>());
2745 mRowStretchFactors.append(1);
2745 mRowStretchFactors.append(1);
2746 }
2746 }
2747 // go through rows and expand columns as necessary:
2747 // go through rows and expand columns as necessary:
2748 int newColCount = qMax(columnCount(), newColumnCount);
2748 int newColCount = qMax(columnCount(), newColumnCount);
2749 for (int i=0; i<rowCount(); ++i)
2749 for (int i=0; i<rowCount(); ++i)
2750 {
2750 {
2751 while (mElements.at(i).size() < newColCount)
2751 while (mElements.at(i).size() < newColCount)
2752 mElements[i].append(0);
2752 mElements[i].append(0);
2753 }
2753 }
2754 while (mColumnStretchFactors.size() < newColCount)
2754 while (mColumnStretchFactors.size() < newColCount)
2755 mColumnStretchFactors.append(1);
2755 mColumnStretchFactors.append(1);
2756 }
2756 }
2757
2757
2758 /*!
2758 /*!
@@ -2763,22 +2763,22 void QCPLayoutGrid::expandTo(int newRowC
2763 */
2763 */
2764 void QCPLayoutGrid::insertRow(int newIndex)
2764 void QCPLayoutGrid::insertRow(int newIndex)
2765 {
2765 {
2766 if (mElements.isEmpty() || mElements.first().isEmpty()) // if grid is completely empty, add first cell
2766 if (mElements.isEmpty() || mElements.first().isEmpty()) // if grid is completely empty, add first cell
2767 {
2767 {
2768 expandTo(1, 1);
2768 expandTo(1, 1);
2769 return;
2769 return;
2770 }
2770 }
2771
2771
2772 if (newIndex < 0)
2772 if (newIndex < 0)
2773 newIndex = 0;
2773 newIndex = 0;
2774 if (newIndex > rowCount())
2774 if (newIndex > rowCount())
2775 newIndex = rowCount();
2775 newIndex = rowCount();
2776
2776
2777 mRowStretchFactors.insert(newIndex, 1);
2777 mRowStretchFactors.insert(newIndex, 1);
2778 QList<QCPLayoutElement*> newRow;
2778 QList<QCPLayoutElement*> newRow;
2779 for (int col=0; col<columnCount(); ++col)
2779 for (int col=0; col<columnCount(); ++col)
2780 newRow.append((QCPLayoutElement*)0);
2780 newRow.append((QCPLayoutElement*)0);
2781 mElements.insert(newIndex, newRow);
2781 mElements.insert(newIndex, newRow);
2782 }
2782 }
2783
2783
2784 /*!
2784 /*!
@@ -2789,47 +2789,47 void QCPLayoutGrid::insertRow(int newInd
2789 */
2789 */
2790 void QCPLayoutGrid::insertColumn(int newIndex)
2790 void QCPLayoutGrid::insertColumn(int newIndex)
2791 {
2791 {
2792 if (mElements.isEmpty() || mElements.first().isEmpty()) // if grid is completely empty, add first cell
2792 if (mElements.isEmpty() || mElements.first().isEmpty()) // if grid is completely empty, add first cell
2793 {
2793 {
2794 expandTo(1, 1);
2794 expandTo(1, 1);
2795 return;
2795 return;
2796 }
2796 }
2797
2797
2798 if (newIndex < 0)
2798 if (newIndex < 0)
2799 newIndex = 0;
2799 newIndex = 0;
2800 if (newIndex > columnCount())
2800 if (newIndex > columnCount())
2801 newIndex = columnCount();
2801 newIndex = columnCount();
2802
2802
2803 mColumnStretchFactors.insert(newIndex, 1);
2803 mColumnStretchFactors.insert(newIndex, 1);
2804 for (int row=0; row<rowCount(); ++row)
2804 for (int row=0; row<rowCount(); ++row)
2805 mElements[row].insert(newIndex, (QCPLayoutElement*)0);
2805 mElements[row].insert(newIndex, (QCPLayoutElement*)0);
2806 }
2806 }
2807
2807
2808 /* inherits documentation from base class */
2808 /* inherits documentation from base class */
2809 void QCPLayoutGrid::updateLayout()
2809 void QCPLayoutGrid::updateLayout()
2810 {
2810 {
2811 QVector<int> minColWidths, minRowHeights, maxColWidths, maxRowHeights;
2811 QVector<int> minColWidths, minRowHeights, maxColWidths, maxRowHeights;
2812 getMinimumRowColSizes(&minColWidths, &minRowHeights);
2812 getMinimumRowColSizes(&minColWidths, &minRowHeights);
2813 getMaximumRowColSizes(&maxColWidths, &maxRowHeights);
2813 getMaximumRowColSizes(&maxColWidths, &maxRowHeights);
2814
2814
2815 int totalRowSpacing = (rowCount()-1) * mRowSpacing;
2815 int totalRowSpacing = (rowCount()-1) * mRowSpacing;
2816 int totalColSpacing = (columnCount()-1) * mColumnSpacing;
2816 int totalColSpacing = (columnCount()-1) * mColumnSpacing;
2817 QVector<int> colWidths = getSectionSizes(maxColWidths, minColWidths, mColumnStretchFactors.toVector(), mRect.width()-totalColSpacing);
2817 QVector<int> colWidths = getSectionSizes(maxColWidths, minColWidths, mColumnStretchFactors.toVector(), mRect.width()-totalColSpacing);
2818 QVector<int> rowHeights = getSectionSizes(maxRowHeights, minRowHeights, mRowStretchFactors.toVector(), mRect.height()-totalRowSpacing);
2818 QVector<int> rowHeights = getSectionSizes(maxRowHeights, minRowHeights, mRowStretchFactors.toVector(), mRect.height()-totalRowSpacing);
2819
2819
2820 // go through cells and set rects accordingly:
2820 // go through cells and set rects accordingly:
2821 int yOffset = mRect.top();
2821 int yOffset = mRect.top();
2822 for (int row=0; row<rowCount(); ++row)
2822 for (int row=0; row<rowCount(); ++row)
2823 {
2823 {
2824 if (row > 0)
2824 if (row > 0)
2825 yOffset += rowHeights.at(row-1)+mRowSpacing;
2825 yOffset += rowHeights.at(row-1)+mRowSpacing;
2826 int xOffset = mRect.left();
2826 int xOffset = mRect.left();
2827 for (int col=0; col<columnCount(); ++col)
2827 for (int col=0; col<columnCount(); ++col)
2828 {
2828 {
2829 if (col > 0)
2829 if (col > 0)
2830 xOffset += colWidths.at(col-1)+mColumnSpacing;
2830 xOffset += colWidths.at(col-1)+mColumnSpacing;
2831 if (mElements.at(row).at(col))
2831 if (mElements.at(row).at(col))
2832 mElements.at(row).at(col)->setOuterRect(QRect(xOffset, yOffset, colWidths.at(col), rowHeights.at(row)));
2832 mElements.at(row).at(col)->setOuterRect(QRect(xOffset, yOffset, colWidths.at(col), rowHeights.at(row)));
2833 }
2833 }
2834 }
2834 }
2835 }
2835 }
@@ -2837,78 +2837,78 void QCPLayoutGrid::updateLayout()
2837 /* inherits documentation from base class */
2837 /* inherits documentation from base class */
2838 int QCPLayoutGrid::elementCount() const
2838 int QCPLayoutGrid::elementCount() const
2839 {
2839 {
2840 return rowCount()*columnCount();
2840 return rowCount()*columnCount();
2841 }
2841 }
2842
2842
2843 /* inherits documentation from base class */
2843 /* inherits documentation from base class */
2844 QCPLayoutElement *QCPLayoutGrid::elementAt(int index) const
2844 QCPLayoutElement *QCPLayoutGrid::elementAt(int index) const
2845 {
2845 {
2846 if (index >= 0 && index < elementCount())
2846 if (index >= 0 && index < elementCount())
2847 return mElements.at(index / columnCount()).at(index % columnCount());
2847 return mElements.at(index / columnCount()).at(index % columnCount());
2848 else
2848 else
2849 return 0;
2849 return 0;
2850 }
2850 }
2851
2851
2852 /* inherits documentation from base class */
2852 /* inherits documentation from base class */
2853 QCPLayoutElement *QCPLayoutGrid::takeAt(int index)
2853 QCPLayoutElement *QCPLayoutGrid::takeAt(int index)
2854 {
2854 {
2855 if (QCPLayoutElement *el = elementAt(index))
2855 if (QCPLayoutElement *el = elementAt(index))
2856 {
2856 {
2857 releaseElement(el);
2857 releaseElement(el);
2858 mElements[index / columnCount()][index % columnCount()] = 0;
2858 mElements[index / columnCount()][index % columnCount()] = 0;
2859 return el;
2859 return el;
2860 } else
2860 } else
2861 {
2861 {
2862 qDebug() << Q_FUNC_INFO << "Attempt to take invalid index:" << index;
2862 qDebug() << Q_FUNC_INFO << "Attempt to take invalid index:" << index;
2863 return 0;
2863 return 0;
2864 }
2864 }
2865 }
2865 }
2866
2866
2867 /* inherits documentation from base class */
2867 /* inherits documentation from base class */
2868 bool QCPLayoutGrid::take(QCPLayoutElement *element)
2868 bool QCPLayoutGrid::take(QCPLayoutElement *element)
2869 {
2869 {
2870 if (element)
2870 if (element)
2871 {
2871 {
2872 for (int i=0; i<elementCount(); ++i)
2872 for (int i=0; i<elementCount(); ++i)
2873 {
2873 {
2874 if (elementAt(i) == element)
2874 if (elementAt(i) == element)
2875 {
2875 {
2876 takeAt(i);
2876 takeAt(i);
2877 return true;
2877 return true;
2878 }
2878 }
2879 }
2879 }
2880 qDebug() << Q_FUNC_INFO << "Element not in this layout, couldn't take";
2880 qDebug() << Q_FUNC_INFO << "Element not in this layout, couldn't take";
2881 } else
2881 } else
2882 qDebug() << Q_FUNC_INFO << "Can't take null element";
2882 qDebug() << Q_FUNC_INFO << "Can't take null element";
2883 return false;
2883 return false;
2884 }
2884 }
2885
2885
2886 /* inherits documentation from base class */
2886 /* inherits documentation from base class */
2887 QList<QCPLayoutElement*> QCPLayoutGrid::elements(bool recursive) const
2887 QList<QCPLayoutElement*> QCPLayoutGrid::elements(bool recursive) const
2888 {
2888 {
2889 QList<QCPLayoutElement*> result;
2889 QList<QCPLayoutElement*> result;
2890 int colC = columnCount();
2890 int colC = columnCount();
2891 int rowC = rowCount();
2891 int rowC = rowCount();
2892 #if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
2892 #if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
2893 result.reserve(colC*rowC);
2893 result.reserve(colC*rowC);
2894 #endif
2894 #endif
2895 for (int row=0; row<rowC; ++row)
2895 for (int row=0; row<rowC; ++row)
2896 {
2896 {
2897 for (int col=0; col<colC; ++col)
2897 for (int col=0; col<colC; ++col)
2898 {
2898 {
2899 result.append(mElements.at(row).at(col));
2899 result.append(mElements.at(row).at(col));
2900 }
2900 }
2901 }
2901 }
2902 if (recursive)
2902 if (recursive)
2903 {
2903 {
2904 int c = result.size();
2904 int c = result.size();
2905 for (int i=0; i<c; ++i)
2905 for (int i=0; i<c; ++i)
2906 {
2906 {
2907 if (result.at(i))
2907 if (result.at(i))
2908 result << result.at(i)->elements(recursive);
2908 result << result.at(i)->elements(recursive);
2909 }
2909 }
2910 }
2910 }
2911 return result;
2911 return result;
2912 }
2912 }
2913
2913
2914 /*!
2914 /*!
@@ -2916,44 +2916,44 QList<QCPLayoutElement*> QCPLayoutGrid::
2916 */
2916 */
2917 void QCPLayoutGrid::simplify()
2917 void QCPLayoutGrid::simplify()
2918 {
2918 {
2919 // remove rows with only empty cells:
2919 // remove rows with only empty cells:
2920 for (int row=rowCount()-1; row>=0; --row)
2920 for (int row=rowCount()-1; row>=0; --row)
2921 {
2921 {
2922 bool hasElements = false;
2922 bool hasElements = false;
2923 for (int col=0; col<columnCount(); ++col)
2923 for (int col=0; col<columnCount(); ++col)
2924 {
2924 {
2925 if (mElements.at(row).at(col))
2925 if (mElements.at(row).at(col))
2926 {
2926 {
2927 hasElements = true;
2927 hasElements = true;
2928 break;
2928 break;
2929 }
2929 }
2930 }
2930 }
2931 if (!hasElements)
2931 if (!hasElements)
2932 {
2932 {
2933 mRowStretchFactors.removeAt(row);
2933 mRowStretchFactors.removeAt(row);
2934 mElements.removeAt(row);
2934 mElements.removeAt(row);
2935 if (mElements.isEmpty()) // removed last element, also remove stretch factor (wouldn't happen below because also columnCount changed to 0 now)
2935 if (mElements.isEmpty()) // removed last element, also remove stretch factor (wouldn't happen below because also columnCount changed to 0 now)
2936 mColumnStretchFactors.clear();
2936 mColumnStretchFactors.clear();
2937 }
2937 }
2938 }
2938 }
2939
2939
2940 // remove columns with only empty cells:
2940 // remove columns with only empty cells:
2941 for (int col=columnCount()-1; col>=0; --col)
2941 for (int col=columnCount()-1; col>=0; --col)
2942 {
2942 {
2943 bool hasElements = false;
2943 bool hasElements = false;
2944 for (int row=0; row<rowCount(); ++row)
2944 for (int row=0; row<rowCount(); ++row)
2945 {
2945 {
2946 if (mElements.at(row).at(col))
2946 if (mElements.at(row).at(col))
2947 {
2947 {
2948 hasElements = true;
2948 hasElements = true;
2949 break;
2949 break;
2950 }
2950 }
2951 }
2951 }
2952 if (!hasElements)
2952 if (!hasElements)
2953 {
2953 {
2954 mColumnStretchFactors.removeAt(col);
2954 mColumnStretchFactors.removeAt(col);
2955 for (int row=0; row<rowCount(); ++row)
2955 for (int row=0; row<rowCount(); ++row)
2956 mElements[row].removeAt(col);
2956 mElements[row].removeAt(col);
2957 }
2957 }
2958 }
2958 }
2959 }
2959 }
@@ -2961,32 +2961,32 void QCPLayoutGrid::simplify()
2961 /* inherits documentation from base class */
2961 /* inherits documentation from base class */
2962 QSize QCPLayoutGrid::minimumSizeHint() const
2962 QSize QCPLayoutGrid::minimumSizeHint() const
2963 {
2963 {
2964 QVector<int> minColWidths, minRowHeights;
2964 QVector<int> minColWidths, minRowHeights;
2965 getMinimumRowColSizes(&minColWidths, &minRowHeights);
2965 getMinimumRowColSizes(&minColWidths, &minRowHeights);
2966 QSize result(0, 0);
2966 QSize result(0, 0);
2967 for (int i=0; i<minColWidths.size(); ++i)
2967 for (int i=0; i<minColWidths.size(); ++i)
2968 result.rwidth() += minColWidths.at(i);
2968 result.rwidth() += minColWidths.at(i);
2969 for (int i=0; i<minRowHeights.size(); ++i)
2969 for (int i=0; i<minRowHeights.size(); ++i)
2970 result.rheight() += minRowHeights.at(i);
2970 result.rheight() += minRowHeights.at(i);
2971 result.rwidth() += qMax(0, columnCount()-1) * mColumnSpacing + mMargins.left() + mMargins.right();
2971 result.rwidth() += qMax(0, columnCount()-1) * mColumnSpacing + mMargins.left() + mMargins.right();
2972 result.rheight() += qMax(0, rowCount()-1) * mRowSpacing + mMargins.top() + mMargins.bottom();
2972 result.rheight() += qMax(0, rowCount()-1) * mRowSpacing + mMargins.top() + mMargins.bottom();
2973 return result;
2973 return result;
2974 }
2974 }
2975
2975
2976 /* inherits documentation from base class */
2976 /* inherits documentation from base class */
2977 QSize QCPLayoutGrid::maximumSizeHint() const
2977 QSize QCPLayoutGrid::maximumSizeHint() const
2978 {
2978 {
2979 QVector<int> maxColWidths, maxRowHeights;
2979 QVector<int> maxColWidths, maxRowHeights;
2980 getMaximumRowColSizes(&maxColWidths, &maxRowHeights);
2980 getMaximumRowColSizes(&maxColWidths, &maxRowHeights);
2981
2981
2982 QSize result(0, 0);
2982 QSize result(0, 0);
2983 for (int i=0; i<maxColWidths.size(); ++i)
2983 for (int i=0; i<maxColWidths.size(); ++i)
2984 result.setWidth(qMin(result.width()+maxColWidths.at(i), QWIDGETSIZE_MAX));
2984 result.setWidth(qMin(result.width()+maxColWidths.at(i), QWIDGETSIZE_MAX));
2985 for (int i=0; i<maxRowHeights.size(); ++i)
2985 for (int i=0; i<maxRowHeights.size(); ++i)
2986 result.setHeight(qMin(result.height()+maxRowHeights.at(i), QWIDGETSIZE_MAX));
2986 result.setHeight(qMin(result.height()+maxRowHeights.at(i), QWIDGETSIZE_MAX));
2987 result.rwidth() += qMax(0, columnCount()-1) * mColumnSpacing + mMargins.left() + mMargins.right();
2987 result.rwidth() += qMax(0, columnCount()-1) * mColumnSpacing + mMargins.left() + mMargins.right();
2988 result.rheight() += qMax(0, rowCount()-1) * mRowSpacing + mMargins.top() + mMargins.bottom();
2988 result.rheight() += qMax(0, rowCount()-1) * mRowSpacing + mMargins.top() + mMargins.bottom();
2989 return result;
2989 return result;
2990 }
2990 }
2991
2991
2992 /*! \internal
2992 /*! \internal
@@ -3003,21 +3003,21 QSize QCPLayoutGrid::maximumSizeHint() c
3003 */
3003 */
3004 void QCPLayoutGrid::getMinimumRowColSizes(QVector<int> *minColWidths, QVector<int> *minRowHeights) const
3004 void QCPLayoutGrid::getMinimumRowColSizes(QVector<int> *minColWidths, QVector<int> *minRowHeights) const
3005 {
3005 {
3006 *minColWidths = QVector<int>(columnCount(), 0);
3006 *minColWidths = QVector<int>(columnCount(), 0);
3007 *minRowHeights = QVector<int>(rowCount(), 0);
3007 *minRowHeights = QVector<int>(rowCount(), 0);
3008 for (int row=0; row<rowCount(); ++row)
3008 for (int row=0; row<rowCount(); ++row)
3009 {
3009 {
3010 for (int col=0; col<columnCount(); ++col)
3010 for (int col=0; col<columnCount(); ++col)
3011 {
3011 {
3012 if (mElements.at(row).at(col))
3012 if (mElements.at(row).at(col))
3013 {
3013 {
3014 QSize minHint = mElements.at(row).at(col)->minimumSizeHint();
3014 QSize minHint = mElements.at(row).at(col)->minimumSizeHint();
3015 QSize min = mElements.at(row).at(col)->minimumSize();
3015 QSize min = mElements.at(row).at(col)->minimumSize();
3016 QSize final(min.width() > 0 ? min.width() : minHint.width(), min.height() > 0 ? min.height() : minHint.height());
3016 QSize final(min.width() > 0 ? min.width() : minHint.width(), min.height() > 0 ? min.height() : minHint.height());
3017 if (minColWidths->at(col) < final.width())
3017 if (minColWidths->at(col) < final.width())
3018 (*minColWidths)[col] = final.width();
3018 (*minColWidths)[col] = final.width();
3019 if (minRowHeights->at(row) < final.height())
3019 if (minRowHeights->at(row) < final.height())
3020 (*minRowHeights)[row] = final.height();
3020 (*minRowHeights)[row] = final.height();
3021 }
3021 }
3022 }
3022 }
3023 }
3023 }
@@ -3037,21 +3037,21 void QCPLayoutGrid::getMinimumRowColSize
3037 */
3037 */
3038 void QCPLayoutGrid::getMaximumRowColSizes(QVector<int> *maxColWidths, QVector<int> *maxRowHeights) const
3038 void QCPLayoutGrid::getMaximumRowColSizes(QVector<int> *maxColWidths, QVector<int> *maxRowHeights) const
3039 {
3039 {
3040 *maxColWidths = QVector<int>(columnCount(), QWIDGETSIZE_MAX);
3040 *maxColWidths = QVector<int>(columnCount(), QWIDGETSIZE_MAX);
3041 *maxRowHeights = QVector<int>(rowCount(), QWIDGETSIZE_MAX);
3041 *maxRowHeights = QVector<int>(rowCount(), QWIDGETSIZE_MAX);
3042 for (int row=0; row<rowCount(); ++row)
3042 for (int row=0; row<rowCount(); ++row)
3043 {
3043 {
3044 for (int col=0; col<columnCount(); ++col)
3044 for (int col=0; col<columnCount(); ++col)
3045 {
3045 {
3046 if (mElements.at(row).at(col))
3046 if (mElements.at(row).at(col))
3047 {
3047 {
3048 QSize maxHint = mElements.at(row).at(col)->maximumSizeHint();
3048 QSize maxHint = mElements.at(row).at(col)->maximumSizeHint();
3049 QSize max = mElements.at(row).at(col)->maximumSize();
3049 QSize max = mElements.at(row).at(col)->maximumSize();
3050 QSize final(max.width() < QWIDGETSIZE_MAX ? max.width() : maxHint.width(), max.height() < QWIDGETSIZE_MAX ? max.height() : maxHint.height());
3050 QSize final(max.width() < QWIDGETSIZE_MAX ? max.width() : maxHint.width(), max.height() < QWIDGETSIZE_MAX ? max.height() : maxHint.height());
3051 if (maxColWidths->at(col) > final.width())
3051 if (maxColWidths->at(col) > final.width())
3052 (*maxColWidths)[col] = final.width();
3052 (*maxColWidths)[col] = final.width();
3053 if (maxRowHeights->at(row) > final.height())
3053 if (maxRowHeights->at(row) > final.height())
3054 (*maxRowHeights)[row] = final.height();
3054 (*maxRowHeights)[row] = final.height();
3055 }
3055 }
3056 }
3056 }
3057 }
3057 }
@@ -3098,9 +3098,9 QCPLayoutInset::QCPLayoutInset()
3098
3098
3099 QCPLayoutInset::~QCPLayoutInset()
3099 QCPLayoutInset::~QCPLayoutInset()
3100 {
3100 {
3101 // clear all child layout elements. This is important because only the specific layouts know how
3101 // clear all child layout elements. This is important because only the specific layouts know how
3102 // to handle removing elements (clear calls virtual removeAt method to do that).
3102 // to handle removing elements (clear calls virtual removeAt method to do that).
3103 clear();
3103 clear();
3104 }
3104 }
3105
3105
3106 /*!
3106 /*!
@@ -3108,12 +3108,12 QCPLayoutInset::~QCPLayoutInset()
3108 */
3108 */
3109 QCPLayoutInset::InsetPlacement QCPLayoutInset::insetPlacement(int index) const
3109 QCPLayoutInset::InsetPlacement QCPLayoutInset::insetPlacement(int index) const
3110 {
3110 {
3111 if (elementAt(index))
3111 if (elementAt(index))
3112 return mInsetPlacement.at(index);
3112 return mInsetPlacement.at(index);
3113 else
3113 else
3114 {
3114 {
3115 qDebug() << Q_FUNC_INFO << "Invalid element index:" << index;
3115 qDebug() << Q_FUNC_INFO << "Invalid element index:" << index;
3116 return ipFree;
3116 return ipFree;
3117 }
3117 }
3118 }
3118 }
3119
3119
@@ -3123,12 +3123,12 QCPLayoutInset::InsetPlacement QCPLayout
3123 */
3123 */
3124 Qt::Alignment QCPLayoutInset::insetAlignment(int index) const
3124 Qt::Alignment QCPLayoutInset::insetAlignment(int index) const
3125 {
3125 {
3126 if (elementAt(index))
3126 if (elementAt(index))
3127 return mInsetAlignment.at(index);
3127 return mInsetAlignment.at(index);
3128 else
3128 else
3129 {
3129 {
3130 qDebug() << Q_FUNC_INFO << "Invalid element index:" << index;
3130 qDebug() << Q_FUNC_INFO << "Invalid element index:" << index;
3131 return 0;
3131 return 0;
3132 }
3132 }
3133 }
3133 }
3134
3134
@@ -3138,12 +3138,12 Qt::Alignment QCPLayoutInset::insetAlign
3138 */
3138 */
3139 QRectF QCPLayoutInset::insetRect(int index) const
3139 QRectF QCPLayoutInset::insetRect(int index) const
3140 {
3140 {
3141 if (elementAt(index))
3141 if (elementAt(index))
3142 return mInsetRect.at(index);
3142 return mInsetRect.at(index);
3143 else
3143 else
3144 {
3144 {
3145 qDebug() << Q_FUNC_INFO << "Invalid element index:" << index;
3145 qDebug() << Q_FUNC_INFO << "Invalid element index:" << index;
3146 return QRectF();
3146 return QRectF();
3147 }
3147 }
3148 }
3148 }
3149
3149
@@ -3154,10 +3154,10 QRectF QCPLayoutInset::insetRect(int ind
3154 */
3154 */
3155 void QCPLayoutInset::setInsetPlacement(int index, QCPLayoutInset::InsetPlacement placement)
3155 void QCPLayoutInset::setInsetPlacement(int index, QCPLayoutInset::InsetPlacement placement)
3156 {
3156 {
3157 if (elementAt(index))
3157 if (elementAt(index))
3158 mInsetPlacement[index] = placement;
3158 mInsetPlacement[index] = placement;
3159 else
3159 else
3160 qDebug() << Q_FUNC_INFO << "Invalid element index:" << index;
3160 qDebug() << Q_FUNC_INFO << "Invalid element index:" << index;
3161 }
3161 }
3162
3162
3163 /*!
3163 /*!
@@ -3170,10 +3170,10 void QCPLayoutInset::setInsetPlacement(i
3170 */
3170 */
3171 void QCPLayoutInset::setInsetAlignment(int index, Qt::Alignment alignment)
3171 void QCPLayoutInset::setInsetAlignment(int index, Qt::Alignment alignment)
3172 {
3172 {
3173 if (elementAt(index))
3173 if (elementAt(index))
3174 mInsetAlignment[index] = alignment;
3174 mInsetAlignment[index] = alignment;
3175 else
3175 else
3176 qDebug() << Q_FUNC_INFO << "Invalid element index:" << index;
3176 qDebug() << Q_FUNC_INFO << "Invalid element index:" << index;
3177 }
3177 }
3178
3178
3179 /*!
3179 /*!
@@ -3189,104 +3189,104 void QCPLayoutInset::setInsetAlignment(i
3189 */
3189 */
3190 void QCPLayoutInset::setInsetRect(int index, const QRectF &rect)
3190 void QCPLayoutInset::setInsetRect(int index, const QRectF &rect)
3191 {
3191 {
3192 if (elementAt(index))
3192 if (elementAt(index))
3193 mInsetRect[index] = rect;
3193 mInsetRect[index] = rect;
3194 else
3194 else
3195 qDebug() << Q_FUNC_INFO << "Invalid element index:" << index;
3195 qDebug() << Q_FUNC_INFO << "Invalid element index:" << index;
3196 }
3196 }
3197
3197
3198 /* inherits documentation from base class */
3198 /* inherits documentation from base class */
3199 void QCPLayoutInset::updateLayout()
3199 void QCPLayoutInset::updateLayout()
3200 {
3200 {
3201 for (int i=0; i<mElements.size(); ++i)
3201 for (int i=0; i<mElements.size(); ++i)
3202 {
3202 {
3203 QRect insetRect;
3203 QRect insetRect;
3204 QSize finalMinSize, finalMaxSize;
3204 QSize finalMinSize, finalMaxSize;
3205 QSize minSizeHint = mElements.at(i)->minimumSizeHint();
3205 QSize minSizeHint = mElements.at(i)->minimumSizeHint();
3206 QSize maxSizeHint = mElements.at(i)->maximumSizeHint();
3206 QSize maxSizeHint = mElements.at(i)->maximumSizeHint();
3207 finalMinSize.setWidth(mElements.at(i)->minimumSize().width() > 0 ? mElements.at(i)->minimumSize().width() : minSizeHint.width());
3207 finalMinSize.setWidth(mElements.at(i)->minimumSize().width() > 0 ? mElements.at(i)->minimumSize().width() : minSizeHint.width());
3208 finalMinSize.setHeight(mElements.at(i)->minimumSize().height() > 0 ? mElements.at(i)->minimumSize().height() : minSizeHint.height());
3208 finalMinSize.setHeight(mElements.at(i)->minimumSize().height() > 0 ? mElements.at(i)->minimumSize().height() : minSizeHint.height());
3209 finalMaxSize.setWidth(mElements.at(i)->maximumSize().width() < QWIDGETSIZE_MAX ? mElements.at(i)->maximumSize().width() : maxSizeHint.width());
3209 finalMaxSize.setWidth(mElements.at(i)->maximumSize().width() < QWIDGETSIZE_MAX ? mElements.at(i)->maximumSize().width() : maxSizeHint.width());
3210 finalMaxSize.setHeight(mElements.at(i)->maximumSize().height() < QWIDGETSIZE_MAX ? mElements.at(i)->maximumSize().height() : maxSizeHint.height());
3210 finalMaxSize.setHeight(mElements.at(i)->maximumSize().height() < QWIDGETSIZE_MAX ? mElements.at(i)->maximumSize().height() : maxSizeHint.height());
3211 if (mInsetPlacement.at(i) == ipFree)
3211 if (mInsetPlacement.at(i) == ipFree)
3212 {
3212 {
3213 insetRect = QRect(rect().x()+rect().width()*mInsetRect.at(i).x(),
3213 insetRect = QRect(rect().x()+rect().width()*mInsetRect.at(i).x(),
3214 rect().y()+rect().height()*mInsetRect.at(i).y(),
3214 rect().y()+rect().height()*mInsetRect.at(i).y(),
3215 rect().width()*mInsetRect.at(i).width(),
3215 rect().width()*mInsetRect.at(i).width(),
3216 rect().height()*mInsetRect.at(i).height());
3216 rect().height()*mInsetRect.at(i).height());
3217 if (insetRect.size().width() < finalMinSize.width())
3217 if (insetRect.size().width() < finalMinSize.width())
3218 insetRect.setWidth(finalMinSize.width());
3218 insetRect.setWidth(finalMinSize.width());
3219 if (insetRect.size().height() < finalMinSize.height())
3219 if (insetRect.size().height() < finalMinSize.height())
3220 insetRect.setHeight(finalMinSize.height());
3220 insetRect.setHeight(finalMinSize.height());
3221 if (insetRect.size().width() > finalMaxSize.width())
3221 if (insetRect.size().width() > finalMaxSize.width())
3222 insetRect.setWidth(finalMaxSize.width());
3222 insetRect.setWidth(finalMaxSize.width());
3223 if (insetRect.size().height() > finalMaxSize.height())
3223 if (insetRect.size().height() > finalMaxSize.height())
3224 insetRect.setHeight(finalMaxSize.height());
3224 insetRect.setHeight(finalMaxSize.height());
3225 } else if (mInsetPlacement.at(i) == ipBorderAligned)
3225 } else if (mInsetPlacement.at(i) == ipBorderAligned)
3226 {
3226 {
3227 insetRect.setSize(finalMinSize);
3227 insetRect.setSize(finalMinSize);
3228 Qt::Alignment al = mInsetAlignment.at(i);
3228 Qt::Alignment al = mInsetAlignment.at(i);
3229 if (al.testFlag(Qt::AlignLeft)) insetRect.moveLeft(rect().x());
3229 if (al.testFlag(Qt::AlignLeft)) insetRect.moveLeft(rect().x());
3230 else if (al.testFlag(Qt::AlignRight)) insetRect.moveRight(rect().x()+rect().width());
3230 else if (al.testFlag(Qt::AlignRight)) insetRect.moveRight(rect().x()+rect().width());
3231 else insetRect.moveLeft(rect().x()+rect().width()*0.5-finalMinSize.width()*0.5); // default to Qt::AlignHCenter
3231 else insetRect.moveLeft(rect().x()+rect().width()*0.5-finalMinSize.width()*0.5); // default to Qt::AlignHCenter
3232 if (al.testFlag(Qt::AlignTop)) insetRect.moveTop(rect().y());
3232 if (al.testFlag(Qt::AlignTop)) insetRect.moveTop(rect().y());
3233 else if (al.testFlag(Qt::AlignBottom)) insetRect.moveBottom(rect().y()+rect().height());
3233 else if (al.testFlag(Qt::AlignBottom)) insetRect.moveBottom(rect().y()+rect().height());
3234 else insetRect.moveTop(rect().y()+rect().height()*0.5-finalMinSize.height()*0.5); // default to Qt::AlignVCenter
3234 else insetRect.moveTop(rect().y()+rect().height()*0.5-finalMinSize.height()*0.5); // default to Qt::AlignVCenter
3235 }
3235 }
3236 mElements.at(i)->setOuterRect(insetRect);
3236 mElements.at(i)->setOuterRect(insetRect);
3237 }
3237 }
3238 }
3238 }
3239
3239
3240 /* inherits documentation from base class */
3240 /* inherits documentation from base class */
3241 int QCPLayoutInset::elementCount() const
3241 int QCPLayoutInset::elementCount() const
3242 {
3242 {
3243 return mElements.size();
3243 return mElements.size();
3244 }
3244 }
3245
3245
3246 /* inherits documentation from base class */
3246 /* inherits documentation from base class */
3247 QCPLayoutElement *QCPLayoutInset::elementAt(int index) const
3247 QCPLayoutElement *QCPLayoutInset::elementAt(int index) const
3248 {
3248 {
3249 if (index >= 0 && index < mElements.size())
3249 if (index >= 0 && index < mElements.size())
3250 return mElements.at(index);
3250 return mElements.at(index);
3251 else
3251 else
3252 return 0;
3252 return 0;
3253 }
3253 }
3254
3254
3255 /* inherits documentation from base class */
3255 /* inherits documentation from base class */
3256 QCPLayoutElement *QCPLayoutInset::takeAt(int index)
3256 QCPLayoutElement *QCPLayoutInset::takeAt(int index)
3257 {
3257 {
3258 if (QCPLayoutElement *el = elementAt(index))
3258 if (QCPLayoutElement *el = elementAt(index))
3259 {
3259 {
3260 releaseElement(el);
3260 releaseElement(el);
3261 mElements.removeAt(index);
3261 mElements.removeAt(index);
3262 mInsetPlacement.removeAt(index);
3262 mInsetPlacement.removeAt(index);
3263 mInsetAlignment.removeAt(index);
3263 mInsetAlignment.removeAt(index);
3264 mInsetRect.removeAt(index);
3264 mInsetRect.removeAt(index);
3265 return el;
3265 return el;
3266 } else
3266 } else
3267 {
3267 {
3268 qDebug() << Q_FUNC_INFO << "Attempt to take invalid index:" << index;
3268 qDebug() << Q_FUNC_INFO << "Attempt to take invalid index:" << index;
3269 return 0;
3269 return 0;
3270 }
3270 }
3271 }
3271 }
3272
3272
3273 /* inherits documentation from base class */
3273 /* inherits documentation from base class */
3274 bool QCPLayoutInset::take(QCPLayoutElement *element)
3274 bool QCPLayoutInset::take(QCPLayoutElement *element)
3275 {
3275 {
3276 if (element)
3276 if (element)
3277 {
3277 {
3278 for (int i=0; i<elementCount(); ++i)
3278 for (int i=0; i<elementCount(); ++i)
3279 {
3279 {
3280 if (elementAt(i) == element)
3280 if (elementAt(i) == element)
3281 {
3281 {
3282 takeAt(i);
3282 takeAt(i);
3283 return true;
3283 return true;
3284 }
3284 }
3285 }
3285 }
3286 qDebug() << Q_FUNC_INFO << "Element not in this layout, couldn't take";
3286 qDebug() << Q_FUNC_INFO << "Element not in this layout, couldn't take";
3287 } else
3287 } else
3288 qDebug() << Q_FUNC_INFO << "Can't take null element";
3288 qDebug() << Q_FUNC_INFO << "Can't take null element";
3289 return false;
3289 return false;
3290 }
3290 }
3291
3291
3292 /*!
3292 /*!
@@ -3300,18 +3300,18 bool QCPLayoutInset::take(QCPLayoutEleme
3300 */
3300 */
3301 double QCPLayoutInset::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
3301 double QCPLayoutInset::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
3302 {
3302 {
3303 Q_UNUSED(details)
3303 Q_UNUSED(details)
3304 if (onlySelectable)
3304 if (onlySelectable)
3305 return -1;
3306
3307 for (int i=0; i<mElements.size(); ++i)
3308 {
3309 // inset layout shall only return positive selectTest, if actually an inset object is at pos
3310 // else it would block the entire underlying QCPAxisRect with its surface.
3311 if (mElements.at(i)->realVisibility() && mElements.at(i)->selectTest(pos, onlySelectable) >= 0)
3312 return mParentPlot->selectionTolerance()*0.99;
3313 }
3305 return -1;
3314 return -1;
3306
3307 for (int i=0; i<mElements.size(); ++i)
3308 {
3309 // inset layout shall only return positive selectTest, if actually an inset object is at pos
3310 // else it would block the entire underlying QCPAxisRect with its surface.
3311 if (mElements.at(i)->realVisibility() && mElements.at(i)->selectTest(pos, onlySelectable) >= 0)
3312 return mParentPlot->selectionTolerance()*0.99;
3313 }
3314 return -1;
3315 }
3315 }
3316
3316
3317 /*!
3317 /*!
@@ -3327,17 +3327,17 double QCPLayoutInset::selectTest(const
3327 */
3327 */
3328 void QCPLayoutInset::addElement(QCPLayoutElement *element, Qt::Alignment alignment)
3328 void QCPLayoutInset::addElement(QCPLayoutElement *element, Qt::Alignment alignment)
3329 {
3329 {
3330 if (element)
3330 if (element)
3331 {
3331 {
3332 if (element->layout()) // remove from old layout first
3332 if (element->layout()) // remove from old layout first
3333 element->layout()->take(element);
3333 element->layout()->take(element);
3334 mElements.append(element);
3334 mElements.append(element);
3335 mInsetPlacement.append(ipBorderAligned);
3335 mInsetPlacement.append(ipBorderAligned);
3336 mInsetAlignment.append(alignment);
3336 mInsetAlignment.append(alignment);
3337 mInsetRect.append(QRectF(0.6, 0.6, 0.4, 0.4));
3337 mInsetRect.append(QRectF(0.6, 0.6, 0.4, 0.4));
3338 adoptElement(element);
3338 adoptElement(element);
3339 } else
3339 } else
3340 qDebug() << Q_FUNC_INFO << "Can't add null element";
3340 qDebug() << Q_FUNC_INFO << "Can't add null element";
3341 }
3341 }
3342
3342
3343 /*!
3343 /*!
@@ -3353,17 +3353,17 void QCPLayoutInset::addElement(QCPLayou
3353 */
3353 */
3354 void QCPLayoutInset::addElement(QCPLayoutElement *element, const QRectF &rect)
3354 void QCPLayoutInset::addElement(QCPLayoutElement *element, const QRectF &rect)
3355 {
3355 {
3356 if (element)
3356 if (element)
3357 {
3357 {
3358 if (element->layout()) // remove from old layout first
3358 if (element->layout()) // remove from old layout first
3359 element->layout()->take(element);
3359 element->layout()->take(element);
3360 mElements.append(element);
3360 mElements.append(element);
3361 mInsetPlacement.append(ipFree);
3361 mInsetPlacement.append(ipFree);
3362 mInsetAlignment.append(Qt::AlignRight|Qt::AlignTop);
3362 mInsetAlignment.append(Qt::AlignRight|Qt::AlignTop);
3363 mInsetRect.append(rect);
3363 mInsetRect.append(rect);
3364 adoptElement(element);
3364 adoptElement(element);
3365 } else
3365 } else
3366 qDebug() << Q_FUNC_INFO << "Can't add null element";
3366 qDebug() << Q_FUNC_INFO << "Can't add null element";
3367 }
3367 }
3368
3368
3369
3369
@@ -3395,10 +3395,10 void QCPLayoutInset::addElement(QCPLayou
3395 Creates a QCPLineEnding instance with default values (style \ref esNone).
3395 Creates a QCPLineEnding instance with default values (style \ref esNone).
3396 */
3396 */
3397 QCPLineEnding::QCPLineEnding() :
3397 QCPLineEnding::QCPLineEnding() :
3398 mStyle(esNone),
3398 mStyle(esNone),
3399 mWidth(8),
3399 mWidth(8),
3400 mLength(10),
3400 mLength(10),
3401 mInverted(false)
3401 mInverted(false)
3402 {
3402 {
3403 }
3403 }
3404
3404
@@ -3406,10 +3406,10 QCPLineEnding::QCPLineEnding() :
3406 Creates a QCPLineEnding instance with the specified values.
3406 Creates a QCPLineEnding instance with the specified values.
3407 */
3407 */
3408 QCPLineEnding::QCPLineEnding(QCPLineEnding::EndingStyle style, double width, double length, bool inverted) :
3408 QCPLineEnding::QCPLineEnding(QCPLineEnding::EndingStyle style, double width, double length, bool inverted) :
3409 mStyle(style),
3409 mStyle(style),
3410 mWidth(width),
3410 mWidth(width),
3411 mLength(length),
3411 mLength(length),
3412 mInverted(inverted)
3412 mInverted(inverted)
3413 {
3413 {
3414 }
3414 }
3415
3415
@@ -3418,7 +3418,7 QCPLineEnding::QCPLineEnding(QCPLineEndi
3418 */
3418 */
3419 void QCPLineEnding::setStyle(QCPLineEnding::EndingStyle style)
3419 void QCPLineEnding::setStyle(QCPLineEnding::EndingStyle style)
3420 {
3420 {
3421 mStyle = style;
3421 mStyle = style;
3422 }
3422 }
3423
3423
3424 /*!
3424 /*!
@@ -3429,7 +3429,7 void QCPLineEnding::setStyle(QCPLineEndi
3429 */
3429 */
3430 void QCPLineEnding::setWidth(double width)
3430 void QCPLineEnding::setWidth(double width)
3431 {
3431 {
3432 mWidth = width;
3432 mWidth = width;
3433 }
3433 }
3434
3434
3435 /*!
3435 /*!
@@ -3440,7 +3440,7 void QCPLineEnding::setWidth(double widt
3440 */
3440 */
3441 void QCPLineEnding::setLength(double length)
3441 void QCPLineEnding::setLength(double length)
3442 {
3442 {
3443 mLength = length;
3443 mLength = length;
3444 }
3444 }
3445
3445
3446 /*!
3446 /*!
@@ -3453,7 +3453,7 void QCPLineEnding::setLength(double len
3453 */
3453 */
3454 void QCPLineEnding::setInverted(bool inverted)
3454 void QCPLineEnding::setInverted(bool inverted)
3455 {
3455 {
3456 mInverted = inverted;
3456 mInverted = inverted;
3457 }
3457 }
3458
3458
3459 /*! \internal
3459 /*! \internal
@@ -3467,26 +3467,26 void QCPLineEnding::setInverted(bool inv
3467 */
3467 */
3468 double QCPLineEnding::boundingDistance() const
3468 double QCPLineEnding::boundingDistance() const
3469 {
3469 {
3470 switch (mStyle)
3470 switch (mStyle)
3471 {
3471 {
3472 case esNone:
3472 case esNone:
3473 return 0;
3473 return 0;
3474
3474
3475 case esFlatArrow:
3475 case esFlatArrow:
3476 case esSpikeArrow:
3476 case esSpikeArrow:
3477 case esLineArrow:
3477 case esLineArrow:
3478 case esSkewedBar:
3478 case esSkewedBar:
3479 return qSqrt(mWidth*mWidth+mLength*mLength); // items that have width and length
3479 return qSqrt(mWidth*mWidth+mLength*mLength); // items that have width and length
3480
3480
3481 case esDisc:
3481 case esDisc:
3482 case esSquare:
3482 case esSquare:
3483 case esDiamond:
3483 case esDiamond:
3484 case esBar:
3484 case esBar:
3485 case esHalfBar:
3485 case esHalfBar:
3486 return mWidth*1.42; // items that only have a width -> width*sqrt(2)
3486 return mWidth*1.42; // items that only have a width -> width*sqrt(2)
3487
3487
3488 }
3488 }
3489 return 0;
3489 return 0;
3490 }
3490 }
3491
3491
3492 /*!
3492 /*!
@@ -3502,27 +3502,27 double QCPLineEnding::boundingDistance()
3502 */
3502 */
3503 double QCPLineEnding::realLength() const
3503 double QCPLineEnding::realLength() const
3504 {
3504 {
3505 switch (mStyle)
3505 switch (mStyle)
3506 {
3506 {
3507 case esNone:
3507 case esNone:
3508 case esLineArrow:
3508 case esLineArrow:
3509 case esSkewedBar:
3509 case esSkewedBar:
3510 case esBar:
3510 case esBar:
3511 case esHalfBar:
3511 case esHalfBar:
3512 return 0;
3512 return 0;
3513
3513
3514 case esFlatArrow:
3514 case esFlatArrow:
3515 return mLength;
3515 return mLength;
3516
3516
3517 case esDisc:
3517 case esDisc:
3518 case esSquare:
3518 case esSquare:
3519 case esDiamond:
3519 case esDiamond:
3520 return mWidth*0.5;
3520 return mWidth*0.5;
3521
3521
3522 case esSpikeArrow:
3522 case esSpikeArrow:
3523 return mLength*0.8;
3523 return mLength*0.8;
3524 }
3524 }
3525 return 0;
3525 return 0;
3526 }
3526 }
3527
3527
3528 /*! \internal
3528 /*! \internal
@@ -3532,26 +3532,26 double QCPLineEnding::realLength() const
3532 */
3532 */
3533 void QCPLineEnding::draw(QCPPainter *painter, const QVector2D &pos, const QVector2D &dir) const
3533 void QCPLineEnding::draw(QCPPainter *painter, const QVector2D &pos, const QVector2D &dir) const
3534 {
3534 {
3535 if (mStyle == esNone)
3535 if (mStyle == esNone)
3536 return;
3536 return;
3537
3537
3538 QVector2D lengthVec(dir.normalized());
3538 QVector2D lengthVec(dir.normalized());
3539 if (lengthVec.isNull())
3539 if (lengthVec.isNull())
3540 lengthVec = QVector2D(1, 0);
3540 lengthVec = QVector2D(1, 0);
3541 QVector2D widthVec(-lengthVec.y(), lengthVec.x());
3541 QVector2D widthVec(-lengthVec.y(), lengthVec.x());
3542 lengthVec *= (float)(mLength*(mInverted ? -1 : 1));
3542 lengthVec *= (float)(mLength*(mInverted ? -1 : 1));
3543 widthVec *= (float)(mWidth*0.5*(mInverted ? -1 : 1));
3543 widthVec *= (float)(mWidth*0.5*(mInverted ? -1 : 1));
3544
3544
3545 QPen penBackup = painter->pen();
3545 QPen penBackup = painter->pen();
3546 QBrush brushBackup = painter->brush();
3546 QBrush brushBackup = painter->brush();
3547 QPen miterPen = penBackup;
3547 QPen miterPen = penBackup;
3548 miterPen.setJoinStyle(Qt::MiterJoin); // to make arrow heads spikey
3548 miterPen.setJoinStyle(Qt::MiterJoin); // to make arrow heads spikey
3549 QBrush brush(painter->pen().color(), Qt::SolidPattern);
3549 QBrush brush(painter->pen().color(), Qt::SolidPattern);
3550 switch (mStyle)
3550 switch (mStyle)
3551 {
3551 {
3552 case esNone: break;
3552 case esNone: break;
3553 case esFlatArrow:
3553 case esFlatArrow:
3554 {
3554 {
3555 QPointF points[3] = {pos.toPointF(),
3555 QPointF points[3] = {pos.toPointF(),
3556 (pos-lengthVec+widthVec).toPointF(),
3556 (pos-lengthVec+widthVec).toPointF(),
3557 (pos-lengthVec-widthVec).toPointF()
3557 (pos-lengthVec-widthVec).toPointF()
@@ -3562,9 +3562,9 void QCPLineEnding::draw(QCPPainter *pai
3562 painter->setBrush(brushBackup);
3562 painter->setBrush(brushBackup);
3563 painter->setPen(penBackup);
3563 painter->setPen(penBackup);
3564 break;
3564 break;
3565 }
3565 }
3566 case esSpikeArrow:
3566 case esSpikeArrow:
3567 {
3567 {
3568 QPointF points[4] = {pos.toPointF(),
3568 QPointF points[4] = {pos.toPointF(),
3569 (pos-lengthVec+widthVec).toPointF(),
3569 (pos-lengthVec+widthVec).toPointF(),
3570 (pos-lengthVec*0.8f).toPointF(),
3570 (pos-lengthVec*0.8f).toPointF(),
@@ -3576,9 +3576,9 void QCPLineEnding::draw(QCPPainter *pai
3576 painter->setBrush(brushBackup);
3576 painter->setBrush(brushBackup);
3577 painter->setPen(penBackup);
3577 painter->setPen(penBackup);
3578 break;
3578 break;
3579 }
3579 }
3580 case esLineArrow:
3580 case esLineArrow:
3581 {
3581 {
3582 QPointF points[3] = {(pos-lengthVec+widthVec).toPointF(),
3582 QPointF points[3] = {(pos-lengthVec+widthVec).toPointF(),
3583 pos.toPointF(),
3583 pos.toPointF(),
3584 (pos-lengthVec-widthVec).toPointF()
3584 (pos-lengthVec-widthVec).toPointF()
@@ -3587,16 +3587,16 void QCPLineEnding::draw(QCPPainter *pai
3587 painter->drawPolyline(points, 3);
3587 painter->drawPolyline(points, 3);
3588 painter->setPen(penBackup);
3588 painter->setPen(penBackup);
3589 break;
3589 break;
3590 }
3590 }
3591 case esDisc:
3591 case esDisc:
3592 {
3592 {
3593 painter->setBrush(brush);
3593 painter->setBrush(brush);
3594 painter->drawEllipse(pos.toPointF(), mWidth*0.5, mWidth*0.5);
3594 painter->drawEllipse(pos.toPointF(), mWidth*0.5, mWidth*0.5);
3595 painter->setBrush(brushBackup);
3595 painter->setBrush(brushBackup);
3596 break;
3596 break;
3597 }
3597 }
3598 case esSquare:
3598 case esSquare:
3599 {
3599 {
3600 QVector2D widthVecPerp(-widthVec.y(), widthVec.x());
3600 QVector2D widthVecPerp(-widthVec.y(), widthVec.x());
3601 QPointF points[4] = {(pos-widthVecPerp+widthVec).toPointF(),
3601 QPointF points[4] = {(pos-widthVecPerp+widthVec).toPointF(),
3602 (pos-widthVecPerp-widthVec).toPointF(),
3602 (pos-widthVecPerp-widthVec).toPointF(),
@@ -3609,9 +3609,9 void QCPLineEnding::draw(QCPPainter *pai
3609 painter->setBrush(brushBackup);
3609 painter->setBrush(brushBackup);
3610 painter->setPen(penBackup);
3610 painter->setPen(penBackup);
3611 break;
3611 break;
3612 }
3612 }
3613 case esDiamond:
3613 case esDiamond:
3614 {
3614 {
3615 QVector2D widthVecPerp(-widthVec.y(), widthVec.x());
3615 QVector2D widthVecPerp(-widthVec.y(), widthVec.x());
3616 QPointF points[4] = {(pos-widthVecPerp).toPointF(),
3616 QPointF points[4] = {(pos-widthVecPerp).toPointF(),
3617 (pos-widthVec).toPointF(),
3617 (pos-widthVec).toPointF(),
@@ -3624,32 +3624,32 void QCPLineEnding::draw(QCPPainter *pai
3624 painter->setBrush(brushBackup);
3624 painter->setBrush(brushBackup);
3625 painter->setPen(penBackup);
3625 painter->setPen(penBackup);
3626 break;
3626 break;
3627 }
3627 }
3628 case esBar:
3628 case esBar:
3629 {
3629 {
3630 painter->drawLine((pos+widthVec).toPointF(), (pos-widthVec).toPointF());
3630 painter->drawLine((pos+widthVec).toPointF(), (pos-widthVec).toPointF());
3631 break;
3631 break;
3632 }
3632 }
3633 case esHalfBar:
3633 case esHalfBar:
3634 {
3634 {
3635 painter->drawLine((pos+widthVec).toPointF(), pos.toPointF());
3635 painter->drawLine((pos+widthVec).toPointF(), pos.toPointF());
3636 break;
3636 break;
3637 }
3637 }
3638 case esSkewedBar:
3638 case esSkewedBar:
3639 {
3639 {
3640 if (qFuzzyIsNull(painter->pen().widthF()) && !painter->modes().testFlag(QCPPainter::pmNonCosmetic))
3640 if (qFuzzyIsNull(painter->pen().widthF()) && !painter->modes().testFlag(QCPPainter::pmNonCosmetic))
3641 {
3641 {
3642 // if drawing with cosmetic pen (perfectly thin stroke, happens only in vector exports), draw bar exactly on tip of line
3642 // if drawing with cosmetic pen (perfectly thin stroke, happens only in vector exports), draw bar exactly on tip of line
3643 painter->drawLine((pos+widthVec+lengthVec*0.2f*(mInverted?-1:1)).toPointF(),
3643 painter->drawLine((pos+widthVec+lengthVec*0.2f*(mInverted?-1:1)).toPointF(),
3644 (pos-widthVec-lengthVec*0.2f*(mInverted?-1:1)).toPointF());
3644 (pos-widthVec-lengthVec*0.2f*(mInverted?-1:1)).toPointF());
3645 } else
3645 } else
3646 {
3646 {
3647 // if drawing with thick (non-cosmetic) pen, shift bar a little in line direction to prevent line from sticking through bar slightly
3647 // if drawing with thick (non-cosmetic) pen, shift bar a little in line direction to prevent line from sticking through bar slightly
3648 painter->drawLine((pos+widthVec+lengthVec*0.2f*(mInverted?-1:1)+dir.normalized()*qMax(1.0f, (float)painter->pen().widthF())*0.5f).toPointF(),
3648 painter->drawLine((pos+widthVec+lengthVec*0.2f*(mInverted?-1:1)+dir.normalized()*qMax(1.0f, (float)painter->pen().widthF())*0.5f).toPointF(),
3649 (pos-widthVec-lengthVec*0.2f*(mInverted?-1:1)+dir.normalized()*qMax(1.0f, (float)painter->pen().widthF())*0.5f).toPointF());
3649 (pos-widthVec-lengthVec*0.2f*(mInverted?-1:1)+dir.normalized()*qMax(1.0f, (float)painter->pen().widthF())*0.5f).toPointF());
3650 }
3650 }
3651 break;
3651 break;
3652 }
3652 }
3653 }
3653 }
3654 }
3654 }
3655
3655
@@ -3660,7 +3660,7 void QCPLineEnding::draw(QCPPainter *pai
3660 */
3660 */
3661 void QCPLineEnding::draw(QCPPainter *painter, const QVector2D &pos, double angle) const
3661 void QCPLineEnding::draw(QCPPainter *painter, const QVector2D &pos, double angle) const
3662 {
3662 {
3663 draw(painter, pos, QVector2D(qCos(angle), qSin(angle)));
3663 draw(painter, pos, QVector2D(qCos(angle), qSin(angle)));
3664 }
3664 }
3665
3665
3666
3666
@@ -3687,18 +3687,18 void QCPLineEnding::draw(QCPPainter *pai
3687 You shouldn't instantiate grids on their own, since every QCPAxis brings its own QCPGrid.
3687 You shouldn't instantiate grids on their own, since every QCPAxis brings its own QCPGrid.
3688 */
3688 */
3689 QCPGrid::QCPGrid(QCPAxis *parentAxis) :
3689 QCPGrid::QCPGrid(QCPAxis *parentAxis) :
3690 QCPLayerable(parentAxis->parentPlot(), QString(), parentAxis),
3690 QCPLayerable(parentAxis->parentPlot(), QString(), parentAxis),
3691 mParentAxis(parentAxis)
3691 mParentAxis(parentAxis)
3692 {
3692 {
3693 // warning: this is called in QCPAxis constructor, so parentAxis members should not be accessed/called
3693 // warning: this is called in QCPAxis constructor, so parentAxis members should not be accessed/called
3694 setParent(parentAxis);
3694 setParent(parentAxis);
3695 setPen(QPen(QColor(200,200,200), 0, Qt::DotLine));
3695 setPen(QPen(QColor(200,200,200), 0, Qt::DotLine));
3696 setSubGridPen(QPen(QColor(220,220,220), 0, Qt::DotLine));
3696 setSubGridPen(QPen(QColor(220,220,220), 0, Qt::DotLine));
3697 setZeroLinePen(QPen(QColor(200,200,200), 0, Qt::SolidLine));
3697 setZeroLinePen(QPen(QColor(200,200,200), 0, Qt::SolidLine));
3698 setSubGridVisible(false);
3698 setSubGridVisible(false);
3699 setAntialiased(false);
3699 setAntialiased(false);
3700 setAntialiasedSubGrid(false);
3700 setAntialiasedSubGrid(false);
3701 setAntialiasedZeroLine(false);
3701 setAntialiasedZeroLine(false);
3702 }
3702 }
3703
3703
3704 /*!
3704 /*!
@@ -3708,7 +3708,7 QCPGrid::QCPGrid(QCPAxis *parentAxis) :
3708 */
3708 */
3709 void QCPGrid::setSubGridVisible(bool visible)
3709 void QCPGrid::setSubGridVisible(bool visible)
3710 {
3710 {
3711 mSubGridVisible = visible;
3711 mSubGridVisible = visible;
3712 }
3712 }
3713
3713
3714 /*!
3714 /*!
@@ -3716,7 +3716,7 void QCPGrid::setSubGridVisible(bool vis
3716 */
3716 */
3717 void QCPGrid::setAntialiasedSubGrid(bool enabled)
3717 void QCPGrid::setAntialiasedSubGrid(bool enabled)
3718 {
3718 {
3719 mAntialiasedSubGrid = enabled;
3719 mAntialiasedSubGrid = enabled;
3720 }
3720 }
3721
3721
3722 /*!
3722 /*!
@@ -3724,7 +3724,7 void QCPGrid::setAntialiasedSubGrid(bool
3724 */
3724 */
3725 void QCPGrid::setAntialiasedZeroLine(bool enabled)
3725 void QCPGrid::setAntialiasedZeroLine(bool enabled)
3726 {
3726 {
3727 mAntialiasedZeroLine = enabled;
3727 mAntialiasedZeroLine = enabled;
3728 }
3728 }
3729
3729
3730 /*!
3730 /*!
@@ -3732,7 +3732,7 void QCPGrid::setAntialiasedZeroLine(boo
3732 */
3732 */
3733 void QCPGrid::setPen(const QPen &pen)
3733 void QCPGrid::setPen(const QPen &pen)
3734 {
3734 {
3735 mPen = pen;
3735 mPen = pen;
3736 }
3736 }
3737
3737
3738 /*!
3738 /*!
@@ -3740,7 +3740,7 void QCPGrid::setPen(const QPen &pen)
3740 */
3740 */
3741 void QCPGrid::setSubGridPen(const QPen &pen)
3741 void QCPGrid::setSubGridPen(const QPen &pen)
3742 {
3742 {
3743 mSubGridPen = pen;
3743 mSubGridPen = pen;
3744 }
3744 }
3745
3745
3746 /*!
3746 /*!
@@ -3751,7 +3751,7 void QCPGrid::setSubGridPen(const QPen &
3751 */
3751 */
3752 void QCPGrid::setZeroLinePen(const QPen &pen)
3752 void QCPGrid::setZeroLinePen(const QPen &pen)
3753 {
3753 {
3754 mZeroLinePen = pen;
3754 mZeroLinePen = pen;
3755 }
3755 }
3756
3756
3757 /*! \internal
3757 /*! \internal
@@ -3769,7 +3769,7 void QCPGrid::setZeroLinePen(const QPen
3769 */
3769 */
3770 void QCPGrid::applyDefaultAntialiasingHint(QCPPainter *painter) const
3770 void QCPGrid::applyDefaultAntialiasingHint(QCPPainter *painter) const
3771 {
3771 {
3772 applyAntialiasingHint(painter, mAntialiased, QCP::aeGrid);
3772 applyAntialiasingHint(painter, mAntialiased, QCP::aeGrid);
3773 }
3773 }
3774
3774
3775 /*! \internal
3775 /*! \internal
@@ -3779,11 +3779,11 void QCPGrid::applyDefaultAntialiasingHi
3779 */
3779 */
3780 void QCPGrid::draw(QCPPainter *painter)
3780 void QCPGrid::draw(QCPPainter *painter)
3781 {
3781 {
3782 if (!mParentAxis) { qDebug() << Q_FUNC_INFO << "invalid parent axis"; return; }
3782 if (!mParentAxis) { qDebug() << Q_FUNC_INFO << "invalid parent axis"; return; }
3783
3783
3784 if (mSubGridVisible)
3784 if (mSubGridVisible)
3785 drawSubGridLines(painter);
3785 drawSubGridLines(painter);
3786 drawGridLines(painter);
3786 drawGridLines(painter);
3787 }
3787 }
3788
3788
3789 /*! \internal
3789 /*! \internal
@@ -3794,68 +3794,68 void QCPGrid::draw(QCPPainter *painter)
3794 */
3794 */
3795 void QCPGrid::drawGridLines(QCPPainter *painter) const
3795 void QCPGrid::drawGridLines(QCPPainter *painter) const
3796 {
3796 {
3797 if (!mParentAxis) { qDebug() << Q_FUNC_INFO << "invalid parent axis"; return; }
3797 if (!mParentAxis) { qDebug() << Q_FUNC_INFO << "invalid parent axis"; return; }
3798
3798
3799 int lowTick = mParentAxis->mLowestVisibleTick;
3799 int lowTick = mParentAxis->mLowestVisibleTick;
3800 int highTick = mParentAxis->mHighestVisibleTick;
3800 int highTick = mParentAxis->mHighestVisibleTick;
3801 double t; // helper variable, result of coordinate-to-pixel transforms
3801 double t; // helper variable, result of coordinate-to-pixel transforms
3802 if (mParentAxis->orientation() == Qt::Horizontal)
3802 if (mParentAxis->orientation() == Qt::Horizontal)
3803 {
3803 {
3804 // draw zeroline:
3804 // draw zeroline:
3805 int zeroLineIndex = -1;
3805 int zeroLineIndex = -1;
3806 if (mZeroLinePen.style() != Qt::NoPen && mParentAxis->mRange.lower < 0 && mParentAxis->mRange.upper > 0)
3806 if (mZeroLinePen.style() != Qt::NoPen && mParentAxis->mRange.lower < 0 && mParentAxis->mRange.upper > 0)
3807 {
3807 {
3808 applyAntialiasingHint(painter, mAntialiasedZeroLine, QCP::aeZeroLine);
3808 applyAntialiasingHint(painter, mAntialiasedZeroLine, QCP::aeZeroLine);
3809 painter->setPen(mZeroLinePen);
3809 painter->setPen(mZeroLinePen);
3810 double epsilon = mParentAxis->range().size()*1E-6; // for comparing double to zero
3810 double epsilon = mParentAxis->range().size()*1E-6; // for comparing double to zero
3811 for (int i=lowTick; i <= highTick; ++i)
3811 for (int i=lowTick; i <= highTick; ++i)
3812 {
3812 {
3813 if (qAbs(mParentAxis->mTickVector.at(i)) < epsilon)
3813 if (qAbs(mParentAxis->mTickVector.at(i)) < epsilon)
3814 {
3814 {
3815 zeroLineIndex = i;
3815 zeroLineIndex = i;
3816 t = mParentAxis->coordToPixel(mParentAxis->mTickVector.at(i)); // x
3816 t = mParentAxis->coordToPixel(mParentAxis->mTickVector.at(i)); // x
3817 painter->drawLine(QLineF(t, mParentAxis->mAxisRect->bottom(), t, mParentAxis->mAxisRect->top()));
3817 painter->drawLine(QLineF(t, mParentAxis->mAxisRect->bottom(), t, mParentAxis->mAxisRect->top()));
3818 break;
3818 break;
3819 }
3819 }
3820 }
3820 }
3821 }
3821 }
3822 // draw grid lines:
3822 // draw grid lines:
3823 applyDefaultAntialiasingHint(painter);
3823 applyDefaultAntialiasingHint(painter);
3824 painter->setPen(mPen);
3824 painter->setPen(mPen);
3825 for (int i=lowTick; i <= highTick; ++i)
3825 for (int i=lowTick; i <= highTick; ++i)
3826 {
3826 {
3827 if (i == zeroLineIndex) continue; // don't draw a gridline on top of the zeroline
3827 if (i == zeroLineIndex) continue; // don't draw a gridline on top of the zeroline
3828 t = mParentAxis->coordToPixel(mParentAxis->mTickVector.at(i)); // x
3828 t = mParentAxis->coordToPixel(mParentAxis->mTickVector.at(i)); // x
3829 painter->drawLine(QLineF(t, mParentAxis->mAxisRect->bottom(), t, mParentAxis->mAxisRect->top()));
3829 painter->drawLine(QLineF(t, mParentAxis->mAxisRect->bottom(), t, mParentAxis->mAxisRect->top()));
3830 }
3830 }
3831 } else
3831 } else
3832 {
3832 {
3833 // draw zeroline:
3833 // draw zeroline:
3834 int zeroLineIndex = -1;
3834 int zeroLineIndex = -1;
3835 if (mZeroLinePen.style() != Qt::NoPen && mParentAxis->mRange.lower < 0 && mParentAxis->mRange.upper > 0)
3835 if (mZeroLinePen.style() != Qt::NoPen && mParentAxis->mRange.lower < 0 && mParentAxis->mRange.upper > 0)
3836 {
3836 {
3837 applyAntialiasingHint(painter, mAntialiasedZeroLine, QCP::aeZeroLine);
3837 applyAntialiasingHint(painter, mAntialiasedZeroLine, QCP::aeZeroLine);
3838 painter->setPen(mZeroLinePen);
3838 painter->setPen(mZeroLinePen);
3839 double epsilon = mParentAxis->mRange.size()*1E-6; // for comparing double to zero
3839 double epsilon = mParentAxis->mRange.size()*1E-6; // for comparing double to zero
3840 for (int i=lowTick; i <= highTick; ++i)
3840 for (int i=lowTick; i <= highTick; ++i)
3841 {
3841 {
3842 if (qAbs(mParentAxis->mTickVector.at(i)) < epsilon)
3842 if (qAbs(mParentAxis->mTickVector.at(i)) < epsilon)
3843 {
3843 {
3844 zeroLineIndex = i;
3844 zeroLineIndex = i;
3845 t = mParentAxis->coordToPixel(mParentAxis->mTickVector.at(i)); // y
3845 t = mParentAxis->coordToPixel(mParentAxis->mTickVector.at(i)); // y
3846 painter->drawLine(QLineF(mParentAxis->mAxisRect->left(), t, mParentAxis->mAxisRect->right(), t));
3846 painter->drawLine(QLineF(mParentAxis->mAxisRect->left(), t, mParentAxis->mAxisRect->right(), t));
3847 break;
3847 break;
3848 }
3848 }
3849 }
3849 }
3850 }
3850 }
3851 // draw grid lines:
3851 // draw grid lines:
3852 applyDefaultAntialiasingHint(painter);
3852 applyDefaultAntialiasingHint(painter);
3853 painter->setPen(mPen);
3853 painter->setPen(mPen);
3854 for (int i=lowTick; i <= highTick; ++i)
3854 for (int i=lowTick; i <= highTick; ++i)
3855 {
3855 {
3856 if (i == zeroLineIndex) continue; // don't draw a gridline on top of the zeroline
3856 if (i == zeroLineIndex) continue; // don't draw a gridline on top of the zeroline
3857 t = mParentAxis->coordToPixel(mParentAxis->mTickVector.at(i)); // y
3857 t = mParentAxis->coordToPixel(mParentAxis->mTickVector.at(i)); // y
3858 painter->drawLine(QLineF(mParentAxis->mAxisRect->left(), t, mParentAxis->mAxisRect->right(), t));
3858 painter->drawLine(QLineF(mParentAxis->mAxisRect->left(), t, mParentAxis->mAxisRect->right(), t));
3859 }
3859 }
3860 }
3860 }
3861 }
3861 }
@@ -3868,24 +3868,24 void QCPGrid::drawGridLines(QCPPainter *
3868 */
3868 */
3869 void QCPGrid::drawSubGridLines(QCPPainter *painter) const
3869 void QCPGrid::drawSubGridLines(QCPPainter *painter) const
3870 {
3870 {
3871 if (!mParentAxis) { qDebug() << Q_FUNC_INFO << "invalid parent axis"; return; }
3871 if (!mParentAxis) { qDebug() << Q_FUNC_INFO << "invalid parent axis"; return; }
3872
3872
3873 applyAntialiasingHint(painter, mAntialiasedSubGrid, QCP::aeSubGrid);
3873 applyAntialiasingHint(painter, mAntialiasedSubGrid, QCP::aeSubGrid);
3874 double t; // helper variable, result of coordinate-to-pixel transforms
3874 double t; // helper variable, result of coordinate-to-pixel transforms
3875 painter->setPen(mSubGridPen);
3875 painter->setPen(mSubGridPen);
3876 if (mParentAxis->orientation() == Qt::Horizontal)
3876 if (mParentAxis->orientation() == Qt::Horizontal)
3877 {
3877 {
3878 for (int i=0; i<mParentAxis->mSubTickVector.size(); ++i)
3878 for (int i=0; i<mParentAxis->mSubTickVector.size(); ++i)
3879 {
3879 {
3880 t = mParentAxis->coordToPixel(mParentAxis->mSubTickVector.at(i)); // x
3880 t = mParentAxis->coordToPixel(mParentAxis->mSubTickVector.at(i)); // x
3881 painter->drawLine(QLineF(t, mParentAxis->mAxisRect->bottom(), t, mParentAxis->mAxisRect->top()));
3881 painter->drawLine(QLineF(t, mParentAxis->mAxisRect->bottom(), t, mParentAxis->mAxisRect->top()));
3882 }
3882 }
3883 } else
3883 } else
3884 {
3884 {
3885 for (int i=0; i<mParentAxis->mSubTickVector.size(); ++i)
3885 for (int i=0; i<mParentAxis->mSubTickVector.size(); ++i)
3886 {
3886 {
3887 t = mParentAxis->coordToPixel(mParentAxis->mSubTickVector.at(i)); // y
3887 t = mParentAxis->coordToPixel(mParentAxis->mSubTickVector.at(i)); // y
3888 painter->drawLine(QLineF(mParentAxis->mAxisRect->left(), t, mParentAxis->mAxisRect->right(), t));
3888 painter->drawLine(QLineF(mParentAxis->mAxisRect->left(), t, mParentAxis->mAxisRect->right(), t));
3889 }
3889 }
3890 }
3890 }
3891 }
3891 }
@@ -3994,167 +3994,167 void QCPGrid::drawSubGridLines(QCPPainte
3994 create them manually and then inject them also via \ref QCPAxisRect::addAxis.
3994 create them manually and then inject them also via \ref QCPAxisRect::addAxis.
3995 */
3995 */
3996 QCPAxis::QCPAxis(QCPAxisRect *parent, AxisType type) :
3996 QCPAxis::QCPAxis(QCPAxisRect *parent, AxisType type) :
3997 QCPLayerable(parent->parentPlot(), QString(), parent),
3997 QCPLayerable(parent->parentPlot(), QString(), parent),
3998 // axis base:
3998 // axis base:
3999 mAxisType(type),
3999 mAxisType(type),
4000 mAxisRect(parent),
4000 mAxisRect(parent),
4001 mPadding(5),
4001 mPadding(5),
4002 mOrientation(orientation(type)),
4002 mOrientation(orientation(type)),
4003 mSelectableParts(spAxis | spTickLabels | spAxisLabel),
4003 mSelectableParts(spAxis | spTickLabels | spAxisLabel),
4004 mSelectedParts(spNone),
4004 mSelectedParts(spNone),
4005 mBasePen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)),
4005 mBasePen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)),
4006 mSelectedBasePen(QPen(Qt::blue, 2)),
4006 mSelectedBasePen(QPen(Qt::blue, 2)),
4007 // axis label:
4007 // axis label:
4008 mLabel(),
4008 mLabel(),
4009 mLabelFont(mParentPlot->font()),
4009 mLabelFont(mParentPlot->font()),
4010 mSelectedLabelFont(QFont(mLabelFont.family(), mLabelFont.pointSize(), QFont::Bold)),
4010 mSelectedLabelFont(QFont(mLabelFont.family(), mLabelFont.pointSize(), QFont::Bold)),
4011 mLabelColor(Qt::black),
4011 mLabelColor(Qt::black),
4012 mSelectedLabelColor(Qt::blue),
4012 mSelectedLabelColor(Qt::blue),
4013 // tick labels:
4013 // tick labels:
4014 mTickLabels(true),
4014 mTickLabels(true),
4015 mAutoTickLabels(true),
4015 mAutoTickLabels(true),
4016 mTickLabelType(ltNumber),
4016 mTickLabelType(ltNumber),
4017 mTickLabelFont(mParentPlot->font()),
4017 mTickLabelFont(mParentPlot->font()),
4018 mSelectedTickLabelFont(QFont(mTickLabelFont.family(), mTickLabelFont.pointSize(), QFont::Bold)),
4018 mSelectedTickLabelFont(QFont(mTickLabelFont.family(), mTickLabelFont.pointSize(), QFont::Bold)),
4019 mTickLabelColor(Qt::black),
4019 mTickLabelColor(Qt::black),
4020 mSelectedTickLabelColor(Qt::blue),
4020 mSelectedTickLabelColor(Qt::blue),
4021 mDateTimeFormat(QLatin1String("hh:mm:ss\ndd.MM.yy")),
4021 mDateTimeFormat(QLatin1String("hh:mm:ss\ndd.MM.yy")),
4022 mDateTimeSpec(Qt::LocalTime),
4022 mDateTimeSpec(Qt::LocalTime),
4023 mNumberPrecision(6),
4023 mNumberPrecision(6),
4024 mNumberFormatChar('g'),
4024 mNumberFormatChar('g'),
4025 mNumberBeautifulPowers(true),
4025 mNumberBeautifulPowers(true),
4026 // ticks and subticks:
4026 // ticks and subticks:
4027 mTicks(true),
4027 mTicks(true),
4028 mTickStep(1),
4028 mTickStep(1),
4029 mSubTickCount(4),
4029 mSubTickCount(4),
4030 mAutoTickCount(6),
4030 mAutoTickCount(6),
4031 mAutoTicks(true),
4031 mAutoTicks(true),
4032 mAutoTickStep(true),
4032 mAutoTickStep(true),
4033 mAutoSubTicks(true),
4033 mAutoSubTicks(true),
4034 mTickPen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)),
4034 mTickPen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)),
4035 mSelectedTickPen(QPen(Qt::blue, 2)),
4035 mSelectedTickPen(QPen(Qt::blue, 2)),
4036 mSubTickPen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)),
4036 mSubTickPen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)),
4037 mSelectedSubTickPen(QPen(Qt::blue, 2)),
4037 mSelectedSubTickPen(QPen(Qt::blue, 2)),
4038 // scale and range:
4038 // scale and range:
4039 mRange(0, 5),
4039 mRange(0, 5),
4040 mRangeReversed(false),
4040 mRangeReversed(false),
4041 mScaleType(stLinear),
4041 mScaleType(stLinear),
4042 mScaleLogBase(10),
4042 mScaleLogBase(10),
4043 mScaleLogBaseLogInv(1.0/qLn(mScaleLogBase)),
4043 mScaleLogBaseLogInv(1.0/qLn(mScaleLogBase)),
4044 // internal members:
4044 // internal members:
4045 mGrid(new QCPGrid(this)),
4045 mGrid(new QCPGrid(this)),
4046 mAxisPainter(new QCPAxisPainterPrivate(parent->parentPlot())),
4046 mAxisPainter(new QCPAxisPainterPrivate(parent->parentPlot())),
4047 mLowestVisibleTick(0),
4047 mLowestVisibleTick(0),
4048 mHighestVisibleTick(-1),
4048 mHighestVisibleTick(-1),
4049 mCachedMarginValid(false),
4049 mCachedMarginValid(false),
4050 mCachedMargin(0)
4050 mCachedMargin(0)
4051 {
4051 {
4052 mGrid->setVisible(false);
4052 mGrid->setVisible(false);
4053 setAntialiased(false);
4053 setAntialiased(false);
4054 setLayer(mParentPlot->currentLayer()); // it's actually on that layer already, but we want it in front of the grid, so we place it on there again
4054 setLayer(mParentPlot->currentLayer()); // it's actually on that layer already, but we want it in front of the grid, so we place it on there again
4055
4055
4056 if (type == atTop)
4056 if (type == atTop)
4057 {
4057 {
4058 setTickLabelPadding(3);
4058 setTickLabelPadding(3);
4059 setLabelPadding(6);
4059 setLabelPadding(6);
4060 } else if (type == atRight)
4060 } else if (type == atRight)
4061 {
4061 {
4062 setTickLabelPadding(7);
4062 setTickLabelPadding(7);
4063 setLabelPadding(12);
4063 setLabelPadding(12);
4064 } else if (type == atBottom)
4064 } else if (type == atBottom)
4065 {
4065 {
4066 setTickLabelPadding(3);
4066 setTickLabelPadding(3);
4067 setLabelPadding(3);
4067 setLabelPadding(3);
4068 } else if (type == atLeft)
4068 } else if (type == atLeft)
4069 {
4069 {
4070 setTickLabelPadding(5);
4070 setTickLabelPadding(5);
4071 setLabelPadding(10);
4071 setLabelPadding(10);
4072 }
4072 }
4073 }
4073 }
4074
4074
4075 QCPAxis::~QCPAxis()
4075 QCPAxis::~QCPAxis()
4076 {
4076 {
4077 delete mAxisPainter;
4077 delete mAxisPainter;
4078 }
4078 }
4079
4079
4080 /* No documentation as it is a property getter */
4080 /* No documentation as it is a property getter */
4081 int QCPAxis::tickLabelPadding() const
4081 int QCPAxis::tickLabelPadding() const
4082 {
4082 {
4083 return mAxisPainter->tickLabelPadding;
4083 return mAxisPainter->tickLabelPadding;
4084 }
4084 }
4085
4085
4086 /* No documentation as it is a property getter */
4086 /* No documentation as it is a property getter */
4087 double QCPAxis::tickLabelRotation() const
4087 double QCPAxis::tickLabelRotation() const
4088 {
4088 {
4089 return mAxisPainter->tickLabelRotation;
4089 return mAxisPainter->tickLabelRotation;
4090 }
4090 }
4091
4091
4092 /* No documentation as it is a property getter */
4092 /* No documentation as it is a property getter */
4093 QCPAxis::LabelSide QCPAxis::tickLabelSide() const
4093 QCPAxis::LabelSide QCPAxis::tickLabelSide() const
4094 {
4094 {
4095 return mAxisPainter->tickLabelSide;
4095 return mAxisPainter->tickLabelSide;
4096 }
4096 }
4097
4097
4098 /* No documentation as it is a property getter */
4098 /* No documentation as it is a property getter */
4099 QString QCPAxis::numberFormat() const
4099 QString QCPAxis::numberFormat() const
4100 {
4100 {
4101 QString result;
4101 QString result;
4102 result.append(mNumberFormatChar);
4102 result.append(mNumberFormatChar);
4103 if (mNumberBeautifulPowers)
4103 if (mNumberBeautifulPowers)
4104 {
4104 {
4105 result.append(QLatin1Char('b'));
4105 result.append(QLatin1Char('b'));
4106 if (mAxisPainter->numberMultiplyCross)
4106 if (mAxisPainter->numberMultiplyCross)
4107 result.append(QLatin1Char('c'));
4107 result.append(QLatin1Char('c'));
4108 }
4108 }
4109 return result;
4109 return result;
4110 }
4110 }
4111
4111
4112 /* No documentation as it is a property getter */
4112 /* No documentation as it is a property getter */
4113 int QCPAxis::tickLengthIn() const
4113 int QCPAxis::tickLengthIn() const
4114 {
4114 {
4115 return mAxisPainter->tickLengthIn;
4115 return mAxisPainter->tickLengthIn;
4116 }
4116 }
4117
4117
4118 /* No documentation as it is a property getter */
4118 /* No documentation as it is a property getter */
4119 int QCPAxis::tickLengthOut() const
4119 int QCPAxis::tickLengthOut() const
4120 {
4120 {
4121 return mAxisPainter->tickLengthOut;
4121 return mAxisPainter->tickLengthOut;
4122 }
4122 }
4123
4123
4124 /* No documentation as it is a property getter */
4124 /* No documentation as it is a property getter */
4125 int QCPAxis::subTickLengthIn() const
4125 int QCPAxis::subTickLengthIn() const
4126 {
4126 {
4127 return mAxisPainter->subTickLengthIn;
4127 return mAxisPainter->subTickLengthIn;
4128 }
4128 }
4129
4129
4130 /* No documentation as it is a property getter */
4130 /* No documentation as it is a property getter */
4131 int QCPAxis::subTickLengthOut() const
4131 int QCPAxis::subTickLengthOut() const
4132 {
4132 {
4133 return mAxisPainter->subTickLengthOut;
4133 return mAxisPainter->subTickLengthOut;
4134 }
4134 }
4135
4135
4136 /* No documentation as it is a property getter */
4136 /* No documentation as it is a property getter */
4137 int QCPAxis::labelPadding() const
4137 int QCPAxis::labelPadding() const
4138 {
4138 {
4139 return mAxisPainter->labelPadding;
4139 return mAxisPainter->labelPadding;
4140 }
4140 }
4141
4141
4142 /* No documentation as it is a property getter */
4142 /* No documentation as it is a property getter */
4143 int QCPAxis::offset() const
4143 int QCPAxis::offset() const
4144 {
4144 {
4145 return mAxisPainter->offset;
4145 return mAxisPainter->offset;
4146 }
4146 }
4147
4147
4148 /* No documentation as it is a property getter */
4148 /* No documentation as it is a property getter */
4149 QCPLineEnding QCPAxis::lowerEnding() const
4149 QCPLineEnding QCPAxis::lowerEnding() const
4150 {
4150 {
4151 return mAxisPainter->lowerEnding;
4151 return mAxisPainter->lowerEnding;
4152 }
4152 }
4153
4153
4154 /* No documentation as it is a property getter */
4154 /* No documentation as it is a property getter */
4155 QCPLineEnding QCPAxis::upperEnding() const
4155 QCPLineEnding QCPAxis::upperEnding() const
4156 {
4156 {
4157 return mAxisPainter->upperEnding;
4157 return mAxisPainter->upperEnding;
4158 }
4158 }
4159
4159
4160 /*!
4160 /*!
@@ -4172,13 +4172,13 QCPLineEnding QCPAxis::upperEnding() con
4172 */
4172 */
4173 void QCPAxis::setScaleType(QCPAxis::ScaleType type)
4173 void QCPAxis::setScaleType(QCPAxis::ScaleType type)
4174 {
4174 {
4175 if (mScaleType != type)
4175 if (mScaleType != type)
4176 {
4176 {
4177 mScaleType = type;
4177 mScaleType = type;
4178 if (mScaleType == stLogarithmic)
4178 if (mScaleType == stLogarithmic)
4179 setRange(mRange.sanitizedForLogScale());
4179 setRange(mRange.sanitizedForLogScale());
4180 mCachedMarginValid = false;
4180 mCachedMarginValid = false;
4181 emit scaleTypeChanged(mScaleType);
4181 emit scaleTypeChanged(mScaleType);
4182 }
4182 }
4183 }
4183 }
4184
4184
@@ -4191,13 +4191,13 void QCPAxis::setScaleType(QCPAxis::Scal
4191 */
4191 */
4192 void QCPAxis::setScaleLogBase(double base)
4192 void QCPAxis::setScaleLogBase(double base)
4193 {
4193 {
4194 if (base > 1)
4194 if (base > 1)
4195 {
4195 {
4196 mScaleLogBase = base;
4196 mScaleLogBase = base;
4197 mScaleLogBaseLogInv = 1.0/qLn(mScaleLogBase); // buffer for faster baseLog() calculation
4197 mScaleLogBaseLogInv = 1.0/qLn(mScaleLogBase); // buffer for faster baseLog() calculation
4198 mCachedMarginValid = false;
4198 mCachedMarginValid = false;
4199 } else
4199 } else
4200 qDebug() << Q_FUNC_INFO << "Invalid logarithmic scale base (must be greater 1):" << base;
4200 qDebug() << Q_FUNC_INFO << "Invalid logarithmic scale base (must be greater 1):" << base;
4201 }
4201 }
4202
4202
4203 /*!
4203 /*!
@@ -4210,21 +4210,21 void QCPAxis::setScaleLogBase(double bas
4210 */
4210 */
4211 void QCPAxis::setRange(const QCPRange &range)
4211 void QCPAxis::setRange(const QCPRange &range)
4212 {
4212 {
4213 if (range.lower == mRange.lower && range.upper == mRange.upper)
4213 if (range.lower == mRange.lower && range.upper == mRange.upper)
4214 return;
4214 return;
4215
4215
4216 if (!QCPRange::validRange(range)) return;
4216 if (!QCPRange::validRange(range)) return;
4217 QCPRange oldRange = mRange;
4217 QCPRange oldRange = mRange;
4218 if (mScaleType == stLogarithmic)
4218 if (mScaleType == stLogarithmic)
4219 {
4219 {
4220 mRange = range.sanitizedForLogScale();
4220 mRange = range.sanitizedForLogScale();
4221 } else
4221 } else
4222 {
4222 {
4223 mRange = range.sanitizedForLinScale();
4223 mRange = range.sanitizedForLinScale();
4224 }
4224 }
4225 mCachedMarginValid = false;
4225 mCachedMarginValid = false;
4226 emit rangeChanged(mRange);
4226 emit rangeChanged(mRange);
4227 emit rangeChanged(mRange, oldRange);
4227 emit rangeChanged(mRange, oldRange);
4228 }
4228 }
4229
4229
4230 /*!
4230 /*!
@@ -4239,10 +4239,10 void QCPAxis::setRange(const QCPRange &r
4239 */
4239 */
4240 void QCPAxis::setSelectableParts(const SelectableParts &selectable)
4240 void QCPAxis::setSelectableParts(const SelectableParts &selectable)
4241 {
4241 {
4242 if (mSelectableParts != selectable)
4242 if (mSelectableParts != selectable)
4243 {
4243 {
4244 mSelectableParts = selectable;
4244 mSelectableParts = selectable;
4245 emit selectableChanged(mSelectableParts);
4245 emit selectableChanged(mSelectableParts);
4246 }
4246 }
4247 }
4247 }
4248
4248
@@ -4263,10 +4263,10 void QCPAxis::setSelectableParts(const S
4263 */
4263 */
4264 void QCPAxis::setSelectedParts(const SelectableParts &selected)
4264 void QCPAxis::setSelectedParts(const SelectableParts &selected)
4265 {
4265 {
4266 if (mSelectedParts != selected)
4266 if (mSelectedParts != selected)
4267 {
4267 {
4268 mSelectedParts = selected;
4268 mSelectedParts = selected;
4269 emit selectionChanged(mSelectedParts);
4269 emit selectionChanged(mSelectedParts);
4270 }
4270 }
4271 }
4271 }
4272
4272
@@ -4281,23 +4281,23 void QCPAxis::setSelectedParts(const Sel
4281 */
4281 */
4282 void QCPAxis::setRange(double lower, double upper)
4282 void QCPAxis::setRange(double lower, double upper)
4283 {
4283 {
4284 if (lower == mRange.lower && upper == mRange.upper)
4284 if (lower == mRange.lower && upper == mRange.upper)
4285 return;
4285 return;
4286
4286
4287 if (!QCPRange::validRange(lower, upper)) return;
4287 if (!QCPRange::validRange(lower, upper)) return;
4288 QCPRange oldRange = mRange;
4288 QCPRange oldRange = mRange;
4289 mRange.lower = lower;
4289 mRange.lower = lower;
4290 mRange.upper = upper;
4290 mRange.upper = upper;
4291 if (mScaleType == stLogarithmic)
4291 if (mScaleType == stLogarithmic)
4292 {
4292 {
4293 mRange = mRange.sanitizedForLogScale();
4293 mRange = mRange.sanitizedForLogScale();
4294 } else
4294 } else
4295 {
4295 {
4296 mRange = mRange.sanitizedForLinScale();
4296 mRange = mRange.sanitizedForLinScale();
4297 }
4297 }
4298 mCachedMarginValid = false;
4298 mCachedMarginValid = false;
4299 emit rangeChanged(mRange);
4299 emit rangeChanged(mRange);
4300 emit rangeChanged(mRange, oldRange);
4300 emit rangeChanged(mRange, oldRange);
4301 }
4301 }
4302
4302
4303 /*!
4303 /*!
@@ -4313,12 +4313,12 void QCPAxis::setRange(double lower, dou
4313 */
4313 */
4314 void QCPAxis::setRange(double position, double size, Qt::AlignmentFlag alignment)
4314 void QCPAxis::setRange(double position, double size, Qt::AlignmentFlag alignment)
4315 {
4315 {
4316 if (alignment == Qt::AlignLeft)
4316 if (alignment == Qt::AlignLeft)
4317 setRange(position, position+size);
4317 setRange(position, position+size);
4318 else if (alignment == Qt::AlignRight)
4318 else if (alignment == Qt::AlignRight)
4319 setRange(position-size, position);
4319 setRange(position-size, position);
4320 else // alignment == Qt::AlignCenter
4320 else // alignment == Qt::AlignCenter
4321 setRange(position-size/2.0, position+size/2.0);
4321 setRange(position-size/2.0, position+size/2.0);
4322 }
4322 }
4323
4323
4324 /*!
4324 /*!
@@ -4327,21 +4327,21 void QCPAxis::setRange(double position,
4327 */
4327 */
4328 void QCPAxis::setRangeLower(double lower)
4328 void QCPAxis::setRangeLower(double lower)
4329 {
4329 {
4330 if (mRange.lower == lower)
4330 if (mRange.lower == lower)
4331 return;
4331 return;
4332
4332
4333 QCPRange oldRange = mRange;
4333 QCPRange oldRange = mRange;
4334 mRange.lower = lower;
4334 mRange.lower = lower;
4335 if (mScaleType == stLogarithmic)
4335 if (mScaleType == stLogarithmic)
4336 {
4336 {
4337 mRange = mRange.sanitizedForLogScale();
4337 mRange = mRange.sanitizedForLogScale();
4338 } else
4338 } else
4339 {
4339 {
4340 mRange = mRange.sanitizedForLinScale();
4340 mRange = mRange.sanitizedForLinScale();
4341 }
4341 }
4342 mCachedMarginValid = false;
4342 mCachedMarginValid = false;
4343 emit rangeChanged(mRange);
4343 emit rangeChanged(mRange);
4344 emit rangeChanged(mRange, oldRange);
4344 emit rangeChanged(mRange, oldRange);
4345 }
4345 }
4346
4346
4347 /*!
4347 /*!
@@ -4350,21 +4350,21 void QCPAxis::setRangeLower(double lower
4350 */
4350 */
4351 void QCPAxis::setRangeUpper(double upper)
4351 void QCPAxis::setRangeUpper(double upper)
4352 {
4352 {
4353 if (mRange.upper == upper)
4353 if (mRange.upper == upper)
4354 return;
4354 return;
4355
4355
4356 QCPRange oldRange = mRange;
4356 QCPRange oldRange = mRange;
4357 mRange.upper = upper;
4357 mRange.upper = upper;
4358 if (mScaleType == stLogarithmic)
4358 if (mScaleType == stLogarithmic)
4359 {
4359 {
4360 mRange = mRange.sanitizedForLogScale();
4360 mRange = mRange.sanitizedForLogScale();
4361 } else
4361 } else
4362 {
4362 {
4363 mRange = mRange.sanitizedForLinScale();
4363 mRange = mRange.sanitizedForLinScale();
4364 }
4364 }
4365 mCachedMarginValid = false;
4365 mCachedMarginValid = false;
4366 emit rangeChanged(mRange);
4366 emit rangeChanged(mRange);
4367 emit rangeChanged(mRange, oldRange);
4367 emit rangeChanged(mRange, oldRange);
4368 }
4368 }
4369
4369
4370 /*!
4370 /*!
@@ -4378,10 +4378,10 void QCPAxis::setRangeUpper(double upper
4378 */
4378 */
4379 void QCPAxis::setRangeReversed(bool reversed)
4379 void QCPAxis::setRangeReversed(bool reversed)
4380 {
4380 {
4381 if (mRangeReversed != reversed)
4381 if (mRangeReversed != reversed)
4382 {
4382 {
4383 mRangeReversed = reversed;
4383 mRangeReversed = reversed;
4384 mCachedMarginValid = false;
4384 mCachedMarginValid = false;
4385 }
4385 }
4386 }
4386 }
4387
4387
@@ -4402,10 +4402,10 void QCPAxis::setRangeReversed(bool reve
4402 */
4402 */
4403 void QCPAxis::setAutoTicks(bool on)
4403 void QCPAxis::setAutoTicks(bool on)
4404 {
4404 {
4405 if (mAutoTicks != on)
4405 if (mAutoTicks != on)
4406 {
4406 {
4407 mAutoTicks = on;
4407 mAutoTicks = on;
4408 mCachedMarginValid = false;
4408 mCachedMarginValid = false;
4409 }
4409 }
4410 }
4410 }
4411
4411
@@ -4422,14 +4422,14 void QCPAxis::setAutoTicks(bool on)
4422 */
4422 */
4423 void QCPAxis::setAutoTickCount(int approximateCount)
4423 void QCPAxis::setAutoTickCount(int approximateCount)
4424 {
4424 {
4425 if (mAutoTickCount != approximateCount)
4425 if (mAutoTickCount != approximateCount)
4426 {
4426 {
4427 if (approximateCount > 0)
4427 if (approximateCount > 0)
4428 {
4428 {
4429 mAutoTickCount = approximateCount;
4429 mAutoTickCount = approximateCount;
4430 mCachedMarginValid = false;
4430 mCachedMarginValid = false;
4431 } else
4431 } else
4432 qDebug() << Q_FUNC_INFO << "approximateCount must be greater than zero:" << approximateCount;
4432 qDebug() << Q_FUNC_INFO << "approximateCount must be greater than zero:" << approximateCount;
4433 }
4433 }
4434 }
4434 }
4435
4435
@@ -4450,10 +4450,10 void QCPAxis::setAutoTickCount(int appro
4450 */
4450 */
4451 void QCPAxis::setAutoTickLabels(bool on)
4451 void QCPAxis::setAutoTickLabels(bool on)
4452 {
4452 {
4453 if (mAutoTickLabels != on)
4453 if (mAutoTickLabels != on)
4454 {
4454 {
4455 mAutoTickLabels = on;
4455 mAutoTickLabels = on;
4456 mCachedMarginValid = false;
4456 mCachedMarginValid = false;
4457 }
4457 }
4458 }
4458 }
4459
4459
@@ -4471,10 +4471,10 void QCPAxis::setAutoTickLabels(bool on)
4471 */
4471 */
4472 void QCPAxis::setAutoTickStep(bool on)
4472 void QCPAxis::setAutoTickStep(bool on)
4473 {
4473 {
4474 if (mAutoTickStep != on)
4474 if (mAutoTickStep != on)
4475 {
4475 {
4476 mAutoTickStep = on;
4476 mAutoTickStep = on;
4477 mCachedMarginValid = false;
4477 mCachedMarginValid = false;
4478 }
4478 }
4479 }
4479 }
4480
4480
@@ -4489,10 +4489,10 void QCPAxis::setAutoTickStep(bool on)
4489 */
4489 */
4490 void QCPAxis::setAutoSubTicks(bool on)
4490 void QCPAxis::setAutoSubTicks(bool on)
4491 {
4491 {
4492 if (mAutoSubTicks != on)
4492 if (mAutoSubTicks != on)
4493 {
4493 {
4494 mAutoSubTicks = on;
4494 mAutoSubTicks = on;
4495 mCachedMarginValid = false;
4495 mCachedMarginValid = false;
4496 }
4496 }
4497 }
4497 }
4498
4498
@@ -4504,10 +4504,10 void QCPAxis::setAutoSubTicks(bool on)
4504 */
4504 */
4505 void QCPAxis::setTicks(bool show)
4505 void QCPAxis::setTicks(bool show)
4506 {
4506 {
4507 if (mTicks != show)
4507 if (mTicks != show)
4508 {
4508 {
4509 mTicks = show;
4509 mTicks = show;
4510 mCachedMarginValid = false;
4510 mCachedMarginValid = false;
4511 }
4511 }
4512 }
4512 }
4513
4513
@@ -4516,10 +4516,10 void QCPAxis::setTicks(bool show)
4516 */
4516 */
4517 void QCPAxis::setTickLabels(bool show)
4517 void QCPAxis::setTickLabels(bool show)
4518 {
4518 {
4519 if (mTickLabels != show)
4519 if (mTickLabels != show)
4520 {
4520 {
4521 mTickLabels = show;
4521 mTickLabels = show;
4522 mCachedMarginValid = false;
4522 mCachedMarginValid = false;
4523 }
4523 }
4524 }
4524 }
4525
4525
@@ -4529,10 +4529,10 void QCPAxis::setTickLabels(bool show)
4529 */
4529 */
4530 void QCPAxis::setTickLabelPadding(int padding)
4530 void QCPAxis::setTickLabelPadding(int padding)
4531 {
4531 {
4532 if (mAxisPainter->tickLabelPadding != padding)
4532 if (mAxisPainter->tickLabelPadding != padding)
4533 {
4533 {
4534 mAxisPainter->tickLabelPadding = padding;
4534 mAxisPainter->tickLabelPadding = padding;
4535 mCachedMarginValid = false;
4535 mCachedMarginValid = false;
4536 }
4536 }
4537 }
4537 }
4538
4538
@@ -4559,10 +4559,10 void QCPAxis::setTickLabelPadding(int pa
4559 */
4559 */
4560 void QCPAxis::setTickLabelType(LabelType type)
4560 void QCPAxis::setTickLabelType(LabelType type)
4561 {
4561 {
4562 if (mTickLabelType != type)
4562 if (mTickLabelType != type)
4563 {
4563 {
4564 mTickLabelType = type;
4564 mTickLabelType = type;
4565 mCachedMarginValid = false;
4565 mCachedMarginValid = false;
4566 }
4566 }
4567 }
4567 }
4568
4568
@@ -4573,10 +4573,10 void QCPAxis::setTickLabelType(LabelType
4573 */
4573 */
4574 void QCPAxis::setTickLabelFont(const QFont &font)
4574 void QCPAxis::setTickLabelFont(const QFont &font)
4575 {
4575 {
4576 if (font != mTickLabelFont)
4576 if (font != mTickLabelFont)
4577 {
4577 {
4578 mTickLabelFont = font;
4578 mTickLabelFont = font;
4579 mCachedMarginValid = false;
4579 mCachedMarginValid = false;
4580 }
4580 }
4581 }
4581 }
4582
4582
@@ -4587,10 +4587,10 void QCPAxis::setTickLabelFont(const QFo
4587 */
4587 */
4588 void QCPAxis::setTickLabelColor(const QColor &color)
4588 void QCPAxis::setTickLabelColor(const QColor &color)
4589 {
4589 {
4590 if (color != mTickLabelColor)
4590 if (color != mTickLabelColor)
4591 {
4591 {
4592 mTickLabelColor = color;
4592 mTickLabelColor = color;
4593 mCachedMarginValid = false;
4593 mCachedMarginValid = false;
4594 }
4594 }
4595 }
4595 }
4596
4596
@@ -4605,10 +4605,10 void QCPAxis::setTickLabelColor(const QC
4605 */
4605 */
4606 void QCPAxis::setTickLabelRotation(double degrees)
4606 void QCPAxis::setTickLabelRotation(double degrees)
4607 {
4607 {
4608 if (!qFuzzyIsNull(degrees-mAxisPainter->tickLabelRotation))
4608 if (!qFuzzyIsNull(degrees-mAxisPainter->tickLabelRotation))
4609 {
4609 {
4610 mAxisPainter->tickLabelRotation = qBound(-90.0, degrees, 90.0);
4610 mAxisPainter->tickLabelRotation = qBound(-90.0, degrees, 90.0);
4611 mCachedMarginValid = false;
4611 mCachedMarginValid = false;
4612 }
4612 }
4613 }
4613 }
4614
4614
@@ -4621,8 +4621,8 void QCPAxis::setTickLabelRotation(doubl
4621 */
4621 */
4622 void QCPAxis::setTickLabelSide(LabelSide side)
4622 void QCPAxis::setTickLabelSide(LabelSide side)
4623 {
4623 {
4624 mAxisPainter->tickLabelSide = side;
4624 mAxisPainter->tickLabelSide = side;
4625 mCachedMarginValid = false;
4625 mCachedMarginValid = false;
4626 }
4626 }
4627
4627
4628 /*!
4628 /*!
@@ -4635,10 +4635,10 void QCPAxis::setTickLabelSide(LabelSide
4635 */
4635 */
4636 void QCPAxis::setDateTimeFormat(const QString &format)
4636 void QCPAxis::setDateTimeFormat(const QString &format)
4637 {
4637 {
4638 if (mDateTimeFormat != format)
4638 if (mDateTimeFormat != format)
4639 {
4639 {
4640 mDateTimeFormat = format;
4640 mDateTimeFormat = format;
4641 mCachedMarginValid = false;
4641 mCachedMarginValid = false;
4642 }
4642 }
4643 }
4643 }
4644
4644
@@ -4654,7 +4654,7 void QCPAxis::setDateTimeFormat(const QS
4654 */
4654 */
4655 void QCPAxis::setDateTimeSpec(const Qt::TimeSpec &timeSpec)
4655 void QCPAxis::setDateTimeSpec(const Qt::TimeSpec &timeSpec)
4656 {
4656 {
4657 mDateTimeSpec = timeSpec;
4657 mDateTimeSpec = timeSpec;
4658 }
4658 }
4659
4659
4660 /*!
4660 /*!
@@ -4695,56 +4695,56 void QCPAxis::setDateTimeSpec(const Qt::
4695 */
4695 */
4696 void QCPAxis::setNumberFormat(const QString &formatCode)
4696 void QCPAxis::setNumberFormat(const QString &formatCode)
4697 {
4697 {
4698 if (formatCode.isEmpty())
4698 if (formatCode.isEmpty())
4699 {
4699 {
4700 qDebug() << Q_FUNC_INFO << "Passed formatCode is empty";
4700 qDebug() << Q_FUNC_INFO << "Passed formatCode is empty";
4701 return;
4701 return;
4702 }
4702 }
4703 mCachedMarginValid = false;
4703 mCachedMarginValid = false;
4704
4704
4705 // interpret first char as number format char:
4705 // interpret first char as number format char:
4706 QString allowedFormatChars(QLatin1String("eEfgG"));
4706 QString allowedFormatChars(QLatin1String("eEfgG"));
4707 if (allowedFormatChars.contains(formatCode.at(0)))
4707 if (allowedFormatChars.contains(formatCode.at(0)))
4708 {
4708 {
4709 mNumberFormatChar = QLatin1Char(formatCode.at(0).toLatin1());
4709 mNumberFormatChar = QLatin1Char(formatCode.at(0).toLatin1());
4710 } else
4710 } else
4711 {
4711 {
4712 qDebug() << Q_FUNC_INFO << "Invalid number format code (first char not in 'eEfgG'):" << formatCode;
4712 qDebug() << Q_FUNC_INFO << "Invalid number format code (first char not in 'eEfgG'):" << formatCode;
4713 return;
4713 return;
4714 }
4714 }
4715 if (formatCode.length() < 2)
4715 if (formatCode.length() < 2)
4716 {
4716 {
4717 mNumberBeautifulPowers = false;
4717 mNumberBeautifulPowers = false;
4718 mAxisPainter->numberMultiplyCross = false;
4718 mAxisPainter->numberMultiplyCross = false;
4719 return;
4719 return;
4720 }
4720 }
4721
4721
4722 // interpret second char as indicator for beautiful decimal powers:
4722 // interpret second char as indicator for beautiful decimal powers:
4723 if (formatCode.at(1) == QLatin1Char('b') && (mNumberFormatChar == QLatin1Char('e') || mNumberFormatChar == QLatin1Char('g')))
4723 if (formatCode.at(1) == QLatin1Char('b') && (mNumberFormatChar == QLatin1Char('e') || mNumberFormatChar == QLatin1Char('g')))
4724 {
4724 {
4725 mNumberBeautifulPowers = true;
4725 mNumberBeautifulPowers = true;
4726 } else
4726 } else
4727 {
4727 {
4728 qDebug() << Q_FUNC_INFO << "Invalid number format code (second char not 'b' or first char neither 'e' nor 'g'):" << formatCode;
4728 qDebug() << Q_FUNC_INFO << "Invalid number format code (second char not 'b' or first char neither 'e' nor 'g'):" << formatCode;
4729 return;
4729 return;
4730 }
4730 }
4731 if (formatCode.length() < 3)
4731 if (formatCode.length() < 3)
4732 {
4732 {
4733 mAxisPainter->numberMultiplyCross = false;
4733 mAxisPainter->numberMultiplyCross = false;
4734 return;
4734 return;
4735 }
4735 }
4736
4736
4737 // interpret third char as indicator for dot or cross multiplication symbol:
4737 // interpret third char as indicator for dot or cross multiplication symbol:
4738 if (formatCode.at(2) == QLatin1Char('c'))
4738 if (formatCode.at(2) == QLatin1Char('c'))
4739 {
4739 {
4740 mAxisPainter->numberMultiplyCross = true;
4740 mAxisPainter->numberMultiplyCross = true;
4741 } else if (formatCode.at(2) == QLatin1Char('d'))
4741 } else if (formatCode.at(2) == QLatin1Char('d'))
4742 {
4742 {
4743 mAxisPainter->numberMultiplyCross = false;
4743 mAxisPainter->numberMultiplyCross = false;
4744 } else
4744 } else
4745 {
4745 {
4746 qDebug() << Q_FUNC_INFO << "Invalid number format code (third char neither 'c' nor 'd'):" << formatCode;
4746 qDebug() << Q_FUNC_INFO << "Invalid number format code (third char neither 'c' nor 'd'):" << formatCode;
4747 return;
4747 return;
4748 }
4748 }
4749 }
4749 }
4750
4750
@@ -4761,10 +4761,10 void QCPAxis::setNumberFormat(const QStr
4761 */
4761 */
4762 void QCPAxis::setNumberPrecision(int precision)
4762 void QCPAxis::setNumberPrecision(int precision)
4763 {
4763 {
4764 if (mNumberPrecision != precision)
4764 if (mNumberPrecision != precision)
4765 {
4765 {
4766 mNumberPrecision = precision;
4766 mNumberPrecision = precision;
4767 mCachedMarginValid = false;
4767 mCachedMarginValid = false;
4768 }
4768 }
4769 }
4769 }
4770
4770
@@ -4775,10 +4775,10 void QCPAxis::setNumberPrecision(int pre
4775 */
4775 */
4776 void QCPAxis::setTickStep(double step)
4776 void QCPAxis::setTickStep(double step)
4777 {
4777 {
4778 if (mTickStep != step)
4778 if (mTickStep != step)
4779 {
4779 {
4780 mTickStep = step;
4780 mTickStep = step;
4781 mCachedMarginValid = false;
4781 mCachedMarginValid = false;
4782 }
4782 }
4783 }
4783 }
4784
4784
@@ -4797,9 +4797,9 void QCPAxis::setTickStep(double step)
4797 */
4797 */
4798 void QCPAxis::setTickVector(const QVector<double> &vec)
4798 void QCPAxis::setTickVector(const QVector<double> &vec)
4799 {
4799 {
4800 // don't check whether mTickVector != vec here, because it takes longer than we would save
4800 // don't check whether mTickVector != vec here, because it takes longer than we would save
4801 mTickVector = vec;
4801 mTickVector = vec;
4802 mCachedMarginValid = false;
4802 mCachedMarginValid = false;
4803 }
4803 }
4804
4804
4805 /*!
4805 /*!
@@ -4815,9 +4815,9 void QCPAxis::setTickVector(const QVecto
4815 */
4815 */
4816 void QCPAxis::setTickVectorLabels(const QVector<QString> &vec)
4816 void QCPAxis::setTickVectorLabels(const QVector<QString> &vec)
4817 {
4817 {
4818 // don't check whether mTickVectorLabels != vec here, because it takes longer than we would save
4818 // don't check whether mTickVectorLabels != vec here, because it takes longer than we would save
4819 mTickVectorLabels = vec;
4819 mTickVectorLabels = vec;
4820 mCachedMarginValid = false;
4820 mCachedMarginValid = false;
4821 }
4821 }
4822
4822
4823 /*!
4823 /*!
@@ -4830,8 +4830,8 void QCPAxis::setTickVectorLabels(const
4830 */
4830 */
4831 void QCPAxis::setTickLength(int inside, int outside)
4831 void QCPAxis::setTickLength(int inside, int outside)
4832 {
4832 {
4833 setTickLengthIn(inside);
4833 setTickLengthIn(inside);
4834 setTickLengthOut(outside);
4834 setTickLengthOut(outside);
4835 }
4835 }
4836
4836
4837 /*!
4837 /*!
@@ -4842,9 +4842,9 void QCPAxis::setTickLength(int inside,
4842 */
4842 */
4843 void QCPAxis::setTickLengthIn(int inside)
4843 void QCPAxis::setTickLengthIn(int inside)
4844 {
4844 {
4845 if (mAxisPainter->tickLengthIn != inside)
4845 if (mAxisPainter->tickLengthIn != inside)
4846 {
4846 {
4847 mAxisPainter->tickLengthIn = inside;
4847 mAxisPainter->tickLengthIn = inside;
4848 }
4848 }
4849 }
4849 }
4850
4850
@@ -4857,10 +4857,10 void QCPAxis::setTickLengthIn(int inside
4857 */
4857 */
4858 void QCPAxis::setTickLengthOut(int outside)
4858 void QCPAxis::setTickLengthOut(int outside)
4859 {
4859 {
4860 if (mAxisPainter->tickLengthOut != outside)
4860 if (mAxisPainter->tickLengthOut != outside)
4861 {
4861 {
4862 mAxisPainter->tickLengthOut = outside;
4862 mAxisPainter->tickLengthOut = outside;
4863 mCachedMarginValid = false; // only outside tick length can change margin
4863 mCachedMarginValid = false; // only outside tick length can change margin
4864 }
4864 }
4865 }
4865 }
4866
4866
@@ -4877,7 +4877,7 void QCPAxis::setTickLengthOut(int outsi
4877 */
4877 */
4878 void QCPAxis::setSubTickCount(int count)
4878 void QCPAxis::setSubTickCount(int count)
4879 {
4879 {
4880 mSubTickCount = count;
4880 mSubTickCount = count;
4881 }
4881 }
4882
4882
4883 /*!
4883 /*!
@@ -4890,8 +4890,8 void QCPAxis::setSubTickCount(int count)
4890 */
4890 */
4891 void QCPAxis::setSubTickLength(int inside, int outside)
4891 void QCPAxis::setSubTickLength(int inside, int outside)
4892 {
4892 {
4893 setSubTickLengthIn(inside);
4893 setSubTickLengthIn(inside);
4894 setSubTickLengthOut(outside);
4894 setSubTickLengthOut(outside);
4895 }
4895 }
4896
4896
4897 /*!
4897 /*!
@@ -4902,9 +4902,9 void QCPAxis::setSubTickLength(int insid
4902 */
4902 */
4903 void QCPAxis::setSubTickLengthIn(int inside)
4903 void QCPAxis::setSubTickLengthIn(int inside)
4904 {
4904 {
4905 if (mAxisPainter->subTickLengthIn != inside)
4905 if (mAxisPainter->subTickLengthIn != inside)
4906 {
4906 {
4907 mAxisPainter->subTickLengthIn = inside;
4907 mAxisPainter->subTickLengthIn = inside;
4908 }
4908 }
4909 }
4909 }
4910
4910
@@ -4917,10 +4917,10 void QCPAxis::setSubTickLengthIn(int ins
4917 */
4917 */
4918 void QCPAxis::setSubTickLengthOut(int outside)
4918 void QCPAxis::setSubTickLengthOut(int outside)
4919 {
4919 {
4920 if (mAxisPainter->subTickLengthOut != outside)
4920 if (mAxisPainter->subTickLengthOut != outside)
4921 {
4921 {
4922 mAxisPainter->subTickLengthOut = outside;
4922 mAxisPainter->subTickLengthOut = outside;
4923 mCachedMarginValid = false; // only outside tick length can change margin
4923 mCachedMarginValid = false; // only outside tick length can change margin
4924 }
4924 }
4925 }
4925 }
4926
4926
@@ -4931,7 +4931,7 void QCPAxis::setSubTickLengthOut(int ou
4931 */
4931 */
4932 void QCPAxis::setBasePen(const QPen &pen)
4932 void QCPAxis::setBasePen(const QPen &pen)
4933 {
4933 {
4934 mBasePen = pen;
4934 mBasePen = pen;
4935 }
4935 }
4936
4936
4937 /*!
4937 /*!
@@ -4941,7 +4941,7 void QCPAxis::setBasePen(const QPen &pen
4941 */
4941 */
4942 void QCPAxis::setTickPen(const QPen &pen)
4942 void QCPAxis::setTickPen(const QPen &pen)
4943 {
4943 {
4944 mTickPen = pen;
4944 mTickPen = pen;
4945 }
4945 }
4946
4946
4947 /*!
4947 /*!
@@ -4951,7 +4951,7 void QCPAxis::setTickPen(const QPen &pen
4951 */
4951 */
4952 void QCPAxis::setSubTickPen(const QPen &pen)
4952 void QCPAxis::setSubTickPen(const QPen &pen)
4953 {
4953 {
4954 mSubTickPen = pen;
4954 mSubTickPen = pen;
4955 }
4955 }
4956
4956
4957 /*!
4957 /*!
@@ -4961,10 +4961,10 void QCPAxis::setSubTickPen(const QPen &
4961 */
4961 */
4962 void QCPAxis::setLabelFont(const QFont &font)
4962 void QCPAxis::setLabelFont(const QFont &font)
4963 {
4963 {
4964 if (mLabelFont != font)
4964 if (mLabelFont != font)
4965 {
4965 {
4966 mLabelFont = font;
4966 mLabelFont = font;
4967 mCachedMarginValid = false;
4967 mCachedMarginValid = false;
4968 }
4968 }
4969 }
4969 }
4970
4970
@@ -4975,7 +4975,7 void QCPAxis::setLabelFont(const QFont &
4975 */
4975 */
4976 void QCPAxis::setLabelColor(const QColor &color)
4976 void QCPAxis::setLabelColor(const QColor &color)
4977 {
4977 {
4978 mLabelColor = color;
4978 mLabelColor = color;
4979 }
4979 }
4980
4980
4981 /*!
4981 /*!
@@ -4984,10 +4984,10 void QCPAxis::setLabelColor(const QColor
4984 */
4984 */
4985 void QCPAxis::setLabel(const QString &str)
4985 void QCPAxis::setLabel(const QString &str)
4986 {
4986 {
4987 if (mLabel != str)
4987 if (mLabel != str)
4988 {
4988 {
4989 mLabel = str;
4989 mLabel = str;
4990 mCachedMarginValid = false;
4990 mCachedMarginValid = false;
4991 }
4991 }
4992 }
4992 }
4993
4993
@@ -4998,10 +4998,10 void QCPAxis::setLabel(const QString &st
4998 */
4998 */
4999 void QCPAxis::setLabelPadding(int padding)
4999 void QCPAxis::setLabelPadding(int padding)
5000 {
5000 {
5001 if (mAxisPainter->labelPadding != padding)
5001 if (mAxisPainter->labelPadding != padding)
5002 {
5002 {
5003 mAxisPainter->labelPadding = padding;
5003 mAxisPainter->labelPadding = padding;
5004 mCachedMarginValid = false;
5004 mCachedMarginValid = false;
5005 }
5005 }
5006 }
5006 }
5007
5007
@@ -5017,10 +5017,10 void QCPAxis::setLabelPadding(int paddin
5017 */
5017 */
5018 void QCPAxis::setPadding(int padding)
5018 void QCPAxis::setPadding(int padding)
5019 {
5019 {
5020 if (mPadding != padding)
5020 if (mPadding != padding)
5021 {
5021 {
5022 mPadding = padding;
5022 mPadding = padding;
5023 mCachedMarginValid = false;
5023 mCachedMarginValid = false;
5024 }
5024 }
5025 }
5025 }
5026
5026
@@ -5034,7 +5034,7 void QCPAxis::setPadding(int padding)
5034 */
5034 */
5035 void QCPAxis::setOffset(int offset)
5035 void QCPAxis::setOffset(int offset)
5036 {
5036 {
5037 mAxisPainter->offset = offset;
5037 mAxisPainter->offset = offset;
5038 }
5038 }
5039
5039
5040 /*!
5040 /*!
@@ -5044,10 +5044,10 void QCPAxis::setOffset(int offset)
5044 */
5044 */
5045 void QCPAxis::setSelectedTickLabelFont(const QFont &font)
5045 void QCPAxis::setSelectedTickLabelFont(const QFont &font)
5046 {
5046 {
5047 if (font != mSelectedTickLabelFont)
5047 if (font != mSelectedTickLabelFont)
5048 {
5048 {
5049 mSelectedTickLabelFont = font;
5049 mSelectedTickLabelFont = font;
5050 // don't set mCachedMarginValid to false here because margin calculation is always done with non-selected fonts
5050 // don't set mCachedMarginValid to false here because margin calculation is always done with non-selected fonts
5051 }
5051 }
5052 }
5052 }
5053
5053
@@ -5058,8 +5058,8 void QCPAxis::setSelectedTickLabelFont(c
5058 */
5058 */
5059 void QCPAxis::setSelectedLabelFont(const QFont &font)
5059 void QCPAxis::setSelectedLabelFont(const QFont &font)
5060 {
5060 {
5061 mSelectedLabelFont = font;
5061 mSelectedLabelFont = font;
5062 // don't set mCachedMarginValid to false here because margin calculation is always done with non-selected fonts
5062 // don't set mCachedMarginValid to false here because margin calculation is always done with non-selected fonts
5063 }
5063 }
5064
5064
5065 /*!
5065 /*!
@@ -5069,9 +5069,9 void QCPAxis::setSelectedLabelFont(const
5069 */
5069 */
5070 void QCPAxis::setSelectedTickLabelColor(const QColor &color)
5070 void QCPAxis::setSelectedTickLabelColor(const QColor &color)
5071 {
5071 {
5072 if (color != mSelectedTickLabelColor)
5072 if (color != mSelectedTickLabelColor)
5073 {
5073 {
5074 mSelectedTickLabelColor = color;
5074 mSelectedTickLabelColor = color;
5075 }
5075 }
5076 }
5076 }
5077
5077
@@ -5082,7 +5082,7 void QCPAxis::setSelectedTickLabelColor(
5082 */
5082 */
5083 void QCPAxis::setSelectedLabelColor(const QColor &color)
5083 void QCPAxis::setSelectedLabelColor(const QColor &color)
5084 {
5084 {
5085 mSelectedLabelColor = color;
5085 mSelectedLabelColor = color;
5086 }
5086 }
5087
5087
5088 /*!
5088 /*!
@@ -5092,7 +5092,7 void QCPAxis::setSelectedLabelColor(cons
5092 */
5092 */
5093 void QCPAxis::setSelectedBasePen(const QPen &pen)
5093 void QCPAxis::setSelectedBasePen(const QPen &pen)
5094 {
5094 {
5095 mSelectedBasePen = pen;
5095 mSelectedBasePen = pen;
5096 }
5096 }
5097
5097
5098 /*!
5098 /*!
@@ -5102,7 +5102,7 void QCPAxis::setSelectedBasePen(const Q
5102 */
5102 */
5103 void QCPAxis::setSelectedTickPen(const QPen &pen)
5103 void QCPAxis::setSelectedTickPen(const QPen &pen)
5104 {
5104 {
5105 mSelectedTickPen = pen;
5105 mSelectedTickPen = pen;
5106 }
5106 }
5107
5107
5108 /*!
5108 /*!
@@ -5112,7 +5112,7 void QCPAxis::setSelectedTickPen(const Q
5112 */
5112 */
5113 void QCPAxis::setSelectedSubTickPen(const QPen &pen)
5113 void QCPAxis::setSelectedSubTickPen(const QPen &pen)
5114 {
5114 {
5115 mSelectedSubTickPen = pen;
5115 mSelectedSubTickPen = pen;
5116 }
5116 }
5117
5117
5118 /*!
5118 /*!
@@ -5127,7 +5127,7 void QCPAxis::setSelectedSubTickPen(cons
5127 */
5127 */
5128 void QCPAxis::setLowerEnding(const QCPLineEnding &ending)
5128 void QCPAxis::setLowerEnding(const QCPLineEnding &ending)
5129 {
5129 {
5130 mAxisPainter->lowerEnding = ending;
5130 mAxisPainter->lowerEnding = ending;
5131 }
5131 }
5132
5132
5133 /*!
5133 /*!
@@ -5142,7 +5142,7 void QCPAxis::setLowerEnding(const QCPLi
5142 */
5142 */
5143 void QCPAxis::setUpperEnding(const QCPLineEnding &ending)
5143 void QCPAxis::setUpperEnding(const QCPLineEnding &ending)
5144 {
5144 {
5145 mAxisPainter->upperEnding = ending;
5145 mAxisPainter->upperEnding = ending;
5146 }
5146 }
5147
5147
5148 /*!
5148 /*!
@@ -5154,19 +5154,19 void QCPAxis::setUpperEnding(const QCPLi
5154 */
5154 */
5155 void QCPAxis::moveRange(double diff)
5155 void QCPAxis::moveRange(double diff)
5156 {
5156 {
5157 QCPRange oldRange = mRange;
5157 QCPRange oldRange = mRange;
5158 if (mScaleType == stLinear)
5158 if (mScaleType == stLinear)
5159 {
5159 {
5160 mRange.lower += diff;
5160 mRange.lower += diff;
5161 mRange.upper += diff;
5161 mRange.upper += diff;
5162 } else // mScaleType == stLogarithmic
5162 } else // mScaleType == stLogarithmic
5163 {
5163 {
5164 mRange.lower *= diff;
5164 mRange.lower *= diff;
5165 mRange.upper *= diff;
5165 mRange.upper *= diff;
5166 }
5166 }
5167 mCachedMarginValid = false;
5167 mCachedMarginValid = false;
5168 emit rangeChanged(mRange);
5168 emit rangeChanged(mRange);
5169 emit rangeChanged(mRange, oldRange);
5169 emit rangeChanged(mRange, oldRange);
5170 }
5170 }
5171
5171
5172 /*!
5172 /*!
@@ -5177,29 +5177,29 void QCPAxis::moveRange(double diff)
5177 */
5177 */
5178 void QCPAxis::scaleRange(double factor, double center)
5178 void QCPAxis::scaleRange(double factor, double center)
5179 {
5179 {
5180 QCPRange oldRange = mRange;
5180 QCPRange oldRange = mRange;
5181 if (mScaleType == stLinear)
5181 if (mScaleType == stLinear)
5182 {
5182 {
5183 QCPRange newRange;
5183 QCPRange newRange;
5184 newRange.lower = (mRange.lower-center)*factor + center;
5184 newRange.lower = (mRange.lower-center)*factor + center;
5185 newRange.upper = (mRange.upper-center)*factor + center;
5185 newRange.upper = (mRange.upper-center)*factor + center;
5186 if (QCPRange::validRange(newRange))
5186 if (QCPRange::validRange(newRange))
5187 mRange = newRange.sanitizedForLinScale();
5187 mRange = newRange.sanitizedForLinScale();
5188 } else // mScaleType == stLogarithmic
5188 } else // mScaleType == stLogarithmic
5189 {
5189 {
5190 if ((mRange.upper < 0 && center < 0) || (mRange.upper > 0 && center > 0)) // make sure center has same sign as range
5190 if ((mRange.upper < 0 && center < 0) || (mRange.upper > 0 && center > 0)) // make sure center has same sign as range
5191 {
5191 {
5192 QCPRange newRange;
5192 QCPRange newRange;
5193 newRange.lower = qPow(mRange.lower/center, factor)*center;
5193 newRange.lower = qPow(mRange.lower/center, factor)*center;
5194 newRange.upper = qPow(mRange.upper/center, factor)*center;
5194 newRange.upper = qPow(mRange.upper/center, factor)*center;
5195 if (QCPRange::validRange(newRange))
5195 if (QCPRange::validRange(newRange))
5196 mRange = newRange.sanitizedForLogScale();
5196 mRange = newRange.sanitizedForLogScale();
5197 } else
5197 } else
5198 qDebug() << Q_FUNC_INFO << "Center of scaling operation doesn't lie in same logarithmic sign domain as range:" << center;
5198 qDebug() << Q_FUNC_INFO << "Center of scaling operation doesn't lie in same logarithmic sign domain as range:" << center;
5199 }
5199 }
5200 mCachedMarginValid = false;
5200 mCachedMarginValid = false;
5201 emit rangeChanged(mRange);
5201 emit rangeChanged(mRange);
5202 emit rangeChanged(mRange, oldRange);
5202 emit rangeChanged(mRange, oldRange);
5203 }
5203 }
5204
5204
5205 /*!
5205 /*!
@@ -5217,20 +5217,20 void QCPAxis::scaleRange(double factor,
5217 */
5217 */
5218 void QCPAxis::setScaleRatio(const QCPAxis *otherAxis, double ratio)
5218 void QCPAxis::setScaleRatio(const QCPAxis *otherAxis, double ratio)
5219 {
5219 {
5220 int otherPixelSize, ownPixelSize;
5220 int otherPixelSize, ownPixelSize;
5221
5221
5222 if (otherAxis->orientation() == Qt::Horizontal)
5222 if (otherAxis->orientation() == Qt::Horizontal)
5223 otherPixelSize = otherAxis->axisRect()->width();
5223 otherPixelSize = otherAxis->axisRect()->width();
5224 else
5224 else
5225 otherPixelSize = otherAxis->axisRect()->height();
5225 otherPixelSize = otherAxis->axisRect()->height();
5226
5226
5227 if (orientation() == Qt::Horizontal)
5227 if (orientation() == Qt::Horizontal)
5228 ownPixelSize = axisRect()->width();
5228 ownPixelSize = axisRect()->width();
5229 else
5229 else
5230 ownPixelSize = axisRect()->height();
5230 ownPixelSize = axisRect()->height();
5231
5231
5232 double newRangeSize = ratio*otherAxis->range().size()*ownPixelSize/(double)otherPixelSize;
5232 double newRangeSize = ratio*otherAxis->range().size()*ownPixelSize/(double)otherPixelSize;
5233 setRange(range().center(), newRangeSize, Qt::AlignCenter);
5233 setRange(range().center(), newRangeSize, Qt::AlignCenter);
5234 }
5234 }
5235
5235
5236 /*!
5236 /*!
@@ -5241,47 +5241,47 void QCPAxis::setScaleRatio(const QCPAxi
5241 */
5241 */
5242 void QCPAxis::rescale(bool onlyVisiblePlottables)
5242 void QCPAxis::rescale(bool onlyVisiblePlottables)
5243 {
5243 {
5244 QList<QCPAbstractPlottable*> p = plottables();
5244 QList<QCPAbstractPlottable*> p = plottables();
5245 QCPRange newRange;
5245 QCPRange newRange;
5246 bool haveRange = false;
5246 bool haveRange = false;
5247 for (int i=0; i<p.size(); ++i)
5247 for (int i=0; i<p.size(); ++i)
5248 {
5248 {
5249 if (!p.at(i)->realVisibility() && onlyVisiblePlottables)
5249 if (!p.at(i)->realVisibility() && onlyVisiblePlottables)
5250 continue;
5250 continue;
5251 QCPRange plottableRange;
5251 QCPRange plottableRange;
5252 bool currentFoundRange;
5252 bool currentFoundRange;
5253 QCPAbstractPlottable::SignDomain signDomain = QCPAbstractPlottable::sdBoth;
5253 QCPAbstractPlottable::SignDomain signDomain = QCPAbstractPlottable::sdBoth;
5254 if (mScaleType == stLogarithmic)
5254 if (mScaleType == stLogarithmic)
5255 signDomain = (mRange.upper < 0 ? QCPAbstractPlottable::sdNegative : QCPAbstractPlottable::sdPositive);
5255 signDomain = (mRange.upper < 0 ? QCPAbstractPlottable::sdNegative : QCPAbstractPlottable::sdPositive);
5256 if (p.at(i)->keyAxis() == this)
5256 if (p.at(i)->keyAxis() == this)
5257 plottableRange = p.at(i)->getKeyRange(currentFoundRange, signDomain);
5257 plottableRange = p.at(i)->getKeyRange(currentFoundRange, signDomain);
5258 else
5258 else
5259 plottableRange = p.at(i)->getValueRange(currentFoundRange, signDomain);
5259 plottableRange = p.at(i)->getValueRange(currentFoundRange, signDomain);
5260 if (currentFoundRange)
5260 if (currentFoundRange)
5261 {
5261 {
5262 if (!haveRange)
5262 if (!haveRange)
5263 newRange = plottableRange;
5263 newRange = plottableRange;
5264 else
5264 else
5265 newRange.expand(plottableRange);
5265 newRange.expand(plottableRange);
5266 haveRange = true;
5266 haveRange = true;
5267 }
5267 }
5268 }
5268 }
5269 if (haveRange)
5269 if (haveRange)
5270 {
5270 {
5271 if (!QCPRange::validRange(newRange)) // likely due to range being zero (plottable has only constant data in this axis dimension), shift current range to at least center the plottable
5271 if (!QCPRange::validRange(newRange)) // likely due to range being zero (plottable has only constant data in this axis dimension), shift current range to at least center the plottable
5272 {
5272 {
5273 double center = (newRange.lower+newRange.upper)*0.5; // upper and lower should be equal anyway, but just to make sure, incase validRange returned false for other reason
5273 double center = (newRange.lower+newRange.upper)*0.5; // upper and lower should be equal anyway, but just to make sure, incase validRange returned false for other reason
5274 if (mScaleType == stLinear)
5274 if (mScaleType == stLinear)
5275 {
5275 {
5276 newRange.lower = center-mRange.size()/2.0;
5276 newRange.lower = center-mRange.size()/2.0;
5277 newRange.upper = center+mRange.size()/2.0;
5277 newRange.upper = center+mRange.size()/2.0;
5278 } else // mScaleType == stLogarithmic
5278 } else // mScaleType == stLogarithmic
5279 {
5279 {
5280 newRange.lower = center/qSqrt(mRange.upper/mRange.lower);
5280 newRange.lower = center/qSqrt(mRange.upper/mRange.lower);
5281 newRange.upper = center*qSqrt(mRange.upper/mRange.lower);
5281 newRange.upper = center*qSqrt(mRange.upper/mRange.lower);
5282 }
5282 }
5283 }
5283 }
5284 setRange(newRange);
5284 setRange(newRange);
5285 }
5285 }
5286 }
5286 }
5287
5287
@@ -5290,35 +5290,35 void QCPAxis::rescale(bool onlyVisiblePl
5290 */
5290 */
5291 double QCPAxis::pixelToCoord(double value) const
5291 double QCPAxis::pixelToCoord(double value) const
5292 {
5292 {
5293 if (orientation() == Qt::Horizontal)
5293 if (orientation() == Qt::Horizontal)
5294 {
5294 {
5295 if (mScaleType == stLinear)
5295 if (mScaleType == stLinear)
5296 {
5296 {
5297 if (!mRangeReversed)
5297 if (!mRangeReversed)
5298 return (value-mAxisRect->left())/(double)mAxisRect->width()*mRange.size()+mRange.lower;
5298 return (value-mAxisRect->left())/(double)mAxisRect->width()*mRange.size()+mRange.lower;
5299 else
5299 else
5300 return -(value-mAxisRect->left())/(double)mAxisRect->width()*mRange.size()+mRange.upper;
5300 return -(value-mAxisRect->left())/(double)mAxisRect->width()*mRange.size()+mRange.upper;
5301 } else // mScaleType == stLogarithmic
5301 } else // mScaleType == stLogarithmic
5302 {
5302 {
5303 if (!mRangeReversed)
5303 if (!mRangeReversed)
5304 return qPow(mRange.upper/mRange.lower, (value-mAxisRect->left())/(double)mAxisRect->width())*mRange.lower;
5304 return qPow(mRange.upper/mRange.lower, (value-mAxisRect->left())/(double)mAxisRect->width())*mRange.lower;
5305 else
5305 else
5306 return qPow(mRange.upper/mRange.lower, (mAxisRect->left()-value)/(double)mAxisRect->width())*mRange.upper;
5306 return qPow(mRange.upper/mRange.lower, (mAxisRect->left()-value)/(double)mAxisRect->width())*mRange.upper;
5307 }
5307 }
5308 } else // orientation() == Qt::Vertical
5308 } else // orientation() == Qt::Vertical
5309 {
5309 {
5310 if (mScaleType == stLinear)
5310 if (mScaleType == stLinear)
5311 {
5311 {
5312 if (!mRangeReversed)
5312 if (!mRangeReversed)
5313 return (mAxisRect->bottom()-value)/(double)mAxisRect->height()*mRange.size()+mRange.lower;
5313 return (mAxisRect->bottom()-value)/(double)mAxisRect->height()*mRange.size()+mRange.lower;
5314 else
5314 else
5315 return -(mAxisRect->bottom()-value)/(double)mAxisRect->height()*mRange.size()+mRange.upper;
5315 return -(mAxisRect->bottom()-value)/(double)mAxisRect->height()*mRange.size()+mRange.upper;
5316 } else // mScaleType == stLogarithmic
5316 } else // mScaleType == stLogarithmic
5317 {
5317 {
5318 if (!mRangeReversed)
5318 if (!mRangeReversed)
5319 return qPow(mRange.upper/mRange.lower, (mAxisRect->bottom()-value)/(double)mAxisRect->height())*mRange.lower;
5319 return qPow(mRange.upper/mRange.lower, (mAxisRect->bottom()-value)/(double)mAxisRect->height())*mRange.lower;
5320 else
5320 else
5321 return qPow(mRange.upper/mRange.lower, (value-mAxisRect->bottom())/(double)mAxisRect->height())*mRange.upper;
5321 return qPow(mRange.upper/mRange.lower, (value-mAxisRect->bottom())/(double)mAxisRect->height())*mRange.upper;
5322 }
5322 }
5323 }
5323 }
5324 }
5324 }
@@ -5328,48 +5328,48 double QCPAxis::pixelToCoord(double valu
5328 */
5328 */
5329 double QCPAxis::coordToPixel(double value) const
5329 double QCPAxis::coordToPixel(double value) const
5330 {
5330 {
5331 if (orientation() == Qt::Horizontal)
5331 if (orientation() == Qt::Horizontal)
5332 {
5332 {
5333 if (mScaleType == stLinear)
5333 if (mScaleType == stLinear)
5334 {
5334 {
5335 if (!mRangeReversed)
5335 if (!mRangeReversed)
5336 return (value-mRange.lower)/mRange.size()*mAxisRect->width()+mAxisRect->left();
5336 return (value-mRange.lower)/mRange.size()*mAxisRect->width()+mAxisRect->left();
5337 else
5337 else
5338 return (mRange.upper-value)/mRange.size()*mAxisRect->width()+mAxisRect->left();
5338 return (mRange.upper-value)/mRange.size()*mAxisRect->width()+mAxisRect->left();
5339 } else // mScaleType == stLogarithmic
5339 } else // mScaleType == stLogarithmic
5340 {
5340 {
5341 if (value >= 0 && mRange.upper < 0) // invalid value for logarithmic scale, just draw it outside visible range
5341 if (value >= 0 && mRange.upper < 0) // invalid value for logarithmic scale, just draw it outside visible range
5342 return !mRangeReversed ? mAxisRect->right()+200 : mAxisRect->left()-200;
5342 return !mRangeReversed ? mAxisRect->right()+200 : mAxisRect->left()-200;
5343 else if (value <= 0 && mRange.upper > 0) // invalid value for logarithmic scale, just draw it outside visible range
5343 else if (value <= 0 && mRange.upper > 0) // invalid value for logarithmic scale, just draw it outside visible range
5344 return !mRangeReversed ? mAxisRect->left()-200 : mAxisRect->right()+200;
5344 return !mRangeReversed ? mAxisRect->left()-200 : mAxisRect->right()+200;
5345 else
5345 else
5346 {
5346 {
5347 if (!mRangeReversed)
5347 if (!mRangeReversed)
5348 return baseLog(value/mRange.lower)/baseLog(mRange.upper/mRange.lower)*mAxisRect->width()+mAxisRect->left();
5348 return baseLog(value/mRange.lower)/baseLog(mRange.upper/mRange.lower)*mAxisRect->width()+mAxisRect->left();
5349 else
5349 else
5350 return baseLog(mRange.upper/value)/baseLog(mRange.upper/mRange.lower)*mAxisRect->width()+mAxisRect->left();
5350 return baseLog(mRange.upper/value)/baseLog(mRange.upper/mRange.lower)*mAxisRect->width()+mAxisRect->left();
5351 }
5351 }
5352 }
5352 }
5353 } else // orientation() == Qt::Vertical
5353 } else // orientation() == Qt::Vertical
5354 {
5354 {
5355 if (mScaleType == stLinear)
5355 if (mScaleType == stLinear)
5356 {
5356 {
5357 if (!mRangeReversed)
5357 if (!mRangeReversed)
5358 return mAxisRect->bottom()-(value-mRange.lower)/mRange.size()*mAxisRect->height();
5358 return mAxisRect->bottom()-(value-mRange.lower)/mRange.size()*mAxisRect->height();
5359 else
5359 else
5360 return mAxisRect->bottom()-(mRange.upper-value)/mRange.size()*mAxisRect->height();
5360 return mAxisRect->bottom()-(mRange.upper-value)/mRange.size()*mAxisRect->height();
5361 } else // mScaleType == stLogarithmic
5361 } else // mScaleType == stLogarithmic
5362 {
5362 {
5363 if (value >= 0 && mRange.upper < 0) // invalid value for logarithmic scale, just draw it outside visible range
5363 if (value >= 0 && mRange.upper < 0) // invalid value for logarithmic scale, just draw it outside visible range
5364 return !mRangeReversed ? mAxisRect->top()-200 : mAxisRect->bottom()+200;
5364 return !mRangeReversed ? mAxisRect->top()-200 : mAxisRect->bottom()+200;
5365 else if (value <= 0 && mRange.upper > 0) // invalid value for logarithmic scale, just draw it outside visible range
5365 else if (value <= 0 && mRange.upper > 0) // invalid value for logarithmic scale, just draw it outside visible range
5366 return !mRangeReversed ? mAxisRect->bottom()+200 : mAxisRect->top()-200;
5366 return !mRangeReversed ? mAxisRect->bottom()+200 : mAxisRect->top()-200;
5367 else
5367 else
5368 {
5368 {
5369 if (!mRangeReversed)
5369 if (!mRangeReversed)
5370 return mAxisRect->bottom()-baseLog(value/mRange.lower)/baseLog(mRange.upper/mRange.lower)*mAxisRect->height();
5370 return mAxisRect->bottom()-baseLog(value/mRange.lower)/baseLog(mRange.upper/mRange.lower)*mAxisRect->height();
5371 else
5371 else
5372 return mAxisRect->bottom()-baseLog(mRange.upper/value)/baseLog(mRange.upper/mRange.lower)*mAxisRect->height();
5372 return mAxisRect->bottom()-baseLog(mRange.upper/value)/baseLog(mRange.upper/mRange.lower)*mAxisRect->height();
5373 }
5373 }
5374 }
5374 }
5375 }
5375 }
@@ -5386,30 +5386,30 double QCPAxis::coordToPixel(double valu
5386 */
5386 */
5387 QCPAxis::SelectablePart QCPAxis::getPartAt(const QPointF &pos) const
5387 QCPAxis::SelectablePart QCPAxis::getPartAt(const QPointF &pos) const
5388 {
5388 {
5389 if (!mVisible)
5389 if (!mVisible)
5390 return spNone;
5390 return spNone;
5391
5391
5392 if (mAxisPainter->axisSelectionBox().contains(pos.toPoint()))
5392 if (mAxisPainter->axisSelectionBox().contains(pos.toPoint()))
5393 return spAxis;
5393 return spAxis;
5394 else if (mAxisPainter->tickLabelsSelectionBox().contains(pos.toPoint()))
5394 else if (mAxisPainter->tickLabelsSelectionBox().contains(pos.toPoint()))
5395 return spTickLabels;
5395 return spTickLabels;
5396 else if (mAxisPainter->labelSelectionBox().contains(pos.toPoint()))
5396 else if (mAxisPainter->labelSelectionBox().contains(pos.toPoint()))
5397 return spAxisLabel;
5397 return spAxisLabel;
5398 else
5398 else
5399 return spNone;
5399 return spNone;
5400 }
5400 }
5401
5401
5402 /* inherits documentation from base class */
5402 /* inherits documentation from base class */
5403 double QCPAxis::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
5403 double QCPAxis::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
5404 {
5404 {
5405 if (!mParentPlot) return -1;
5405 if (!mParentPlot) return -1;
5406 SelectablePart part = getPartAt(pos);
5406 SelectablePart part = getPartAt(pos);
5407 if ((onlySelectable && !mSelectableParts.testFlag(part)) || part == spNone)
5407 if ((onlySelectable && !mSelectableParts.testFlag(part)) || part == spNone)
5408 return -1;
5408 return -1;
5409
5409
5410 if (details)
5410 if (details)
5411 details->setValue(part);
5411 details->setValue(part);
5412 return mParentPlot->selectionTolerance()*0.99;
5412 return mParentPlot->selectionTolerance()*0.99;
5413 }
5413 }
5414
5414
5415 /*!
5415 /*!
@@ -5421,15 +5421,15 double QCPAxis::selectTest(const QPointF
5421 */
5421 */
5422 QList<QCPAbstractPlottable*> QCPAxis::plottables() const
5422 QList<QCPAbstractPlottable*> QCPAxis::plottables() const
5423 {
5423 {
5424 QList<QCPAbstractPlottable*> result;
5424 QList<QCPAbstractPlottable*> result;
5425 if (!mParentPlot) return result;
5425 if (!mParentPlot) return result;
5426
5426
5427 for (int i=0; i<mParentPlot->mPlottables.size(); ++i)
5427 for (int i=0; i<mParentPlot->mPlottables.size(); ++i)
5428 {
5428 {
5429 if (mParentPlot->mPlottables.at(i)->keyAxis() == this ||mParentPlot->mPlottables.at(i)->valueAxis() == this)
5429 if (mParentPlot->mPlottables.at(i)->keyAxis() == this ||mParentPlot->mPlottables.at(i)->valueAxis() == this)
5430 result.append(mParentPlot->mPlottables.at(i));
5430 result.append(mParentPlot->mPlottables.at(i));
5431 }
5431 }
5432 return result;
5432 return result;
5433 }
5433 }
5434
5434
5435 /*!
5435 /*!
@@ -5439,15 +5439,15 QList<QCPAbstractPlottable*> QCPAxis::pl
5439 */
5439 */
5440 QList<QCPGraph*> QCPAxis::graphs() const
5440 QList<QCPGraph*> QCPAxis::graphs() const
5441 {
5441 {
5442 QList<QCPGraph*> result;
5442 QList<QCPGraph*> result;
5443 if (!mParentPlot) return result;
5443 if (!mParentPlot) return result;
5444
5444
5445 for (int i=0; i<mParentPlot->mGraphs.size(); ++i)
5445 for (int i=0; i<mParentPlot->mGraphs.size(); ++i)
5446 {
5446 {
5447 if (mParentPlot->mGraphs.at(i)->keyAxis() == this || mParentPlot->mGraphs.at(i)->valueAxis() == this)
5447 if (mParentPlot->mGraphs.at(i)->keyAxis() == this || mParentPlot->mGraphs.at(i)->valueAxis() == this)
5448 result.append(mParentPlot->mGraphs.at(i));
5448 result.append(mParentPlot->mGraphs.at(i));
5449 }
5449 }
5450 return result;
5450 return result;
5451 }
5451 }
5452
5452
5453 /*!
5453 /*!
@@ -5458,22 +5458,22 QList<QCPGraph*> QCPAxis::graphs() const
5458 */
5458 */
5459 QList<QCPAbstractItem*> QCPAxis::items() const
5459 QList<QCPAbstractItem*> QCPAxis::items() const
5460 {
5460 {
5461 QList<QCPAbstractItem*> result;
5461 QList<QCPAbstractItem*> result;
5462 if (!mParentPlot) return result;
5462 if (!mParentPlot) return result;
5463
5463
5464 for (int itemId=0; itemId<mParentPlot->mItems.size(); ++itemId)
5464 for (int itemId=0; itemId<mParentPlot->mItems.size(); ++itemId)
5465 {
5465 {
5466 QList<QCPItemPosition*> positions = mParentPlot->mItems.at(itemId)->positions();
5466 QList<QCPItemPosition*> positions = mParentPlot->mItems.at(itemId)->positions();
5467 for (int posId=0; posId<positions.size(); ++posId)
5467 for (int posId=0; posId<positions.size(); ++posId)
5468 {
5468 {
5469 if (positions.at(posId)->keyAxis() == this || positions.at(posId)->valueAxis() == this)
5469 if (positions.at(posId)->keyAxis() == this || positions.at(posId)->valueAxis() == this)
5470 {
5470 {
5471 result.append(mParentPlot->mItems.at(itemId));
5471 result.append(mParentPlot->mItems.at(itemId));
5472 break;
5472 break;
5473 }
5473 }
5474 }
5474 }
5475 }
5475 }
5476 return result;
5476 return result;
5477 }
5477 }
5478
5478
5479 /*!
5479 /*!
@@ -5482,7 +5482,7 QList<QCPAbstractItem*> QCPAxis::items()
5482 */
5482 */
5483 QCPAxis::AxisType QCPAxis::marginSideToAxisType(QCP::MarginSide side)
5483 QCPAxis::AxisType QCPAxis::marginSideToAxisType(QCP::MarginSide side)
5484 {
5484 {
5485 switch (side)
5485 switch (side)
5486 {
5486 {
5487 case QCP::msLeft: return atLeft;
5487 case QCP::msLeft: return atLeft;
5488 case QCP::msRight: return atRight;
5488 case QCP::msRight: return atRight;
@@ -5490,8 +5490,8 QCPAxis::AxisType QCPAxis::marginSideToA
5490 case QCP::msBottom: return atBottom;
5490 case QCP::msBottom: return atBottom;
5491 default: break;
5491 default: break;
5492 }
5492 }
5493 qDebug() << Q_FUNC_INFO << "Invalid margin side passed:" << (int)side;
5493 qDebug() << Q_FUNC_INFO << "Invalid margin side passed:" << (int)side;
5494 return atLeft;
5494 return atLeft;
5495 }
5495 }
5496
5496
5497 /*!
5497 /*!
@@ -5499,7 +5499,7 QCPAxis::AxisType QCPAxis::marginSideToA
5499 */
5499 */
5500 QCPAxis::AxisType QCPAxis::opposite(QCPAxis::AxisType type)
5500 QCPAxis::AxisType QCPAxis::opposite(QCPAxis::AxisType type)
5501 {
5501 {
5502 switch (type)
5502 switch (type)
5503 {
5503 {
5504 case atLeft: return atRight; break;
5504 case atLeft: return atRight; break;
5505 case atRight: return atLeft; break;
5505 case atRight: return atLeft; break;
@@ -5518,85 +5518,85 QCPAxis::AxisType QCPAxis::opposite(QCPA
5518 */
5518 */
5519 void QCPAxis::setupTickVectors()
5519 void QCPAxis::setupTickVectors()
5520 {
5520 {
5521 if (!mParentPlot) return;
5521 if (!mParentPlot) return;
5522 if ((!mTicks && !mTickLabels && !mGrid->visible()) || mRange.size() <= 0) return;
5522 if ((!mTicks && !mTickLabels && !mGrid->visible()) || mRange.size() <= 0) return;
5523
5523
5524 // fill tick vectors, either by auto generating or by notifying user to fill the vectors himself
5524 // fill tick vectors, either by auto generating or by notifying user to fill the vectors himself
5525 if (mAutoTicks)
5525 if (mAutoTicks)
5526 {
5526 {
5527 generateAutoTicks();
5527 generateAutoTicks();
5528 } else
5528 } else
5529 {
5529 {
5530 emit ticksRequest();
5530 emit ticksRequest();
5531 }
5531 }
5532
5532
5533 visibleTickBounds(mLowestVisibleTick, mHighestVisibleTick);
5533 visibleTickBounds(mLowestVisibleTick, mHighestVisibleTick);
5534 if (mTickVector.isEmpty())
5534 if (mTickVector.isEmpty())
5535 {
5535 {
5536 mSubTickVector.clear();
5536 mSubTickVector.clear();
5537 return;
5537 return;
5538 }
5538 }
5539
5539
5540 // generate subticks between ticks:
5540 // generate subticks between ticks:
5541 mSubTickVector.resize((mTickVector.size()-1)*mSubTickCount);
5541 mSubTickVector.resize((mTickVector.size()-1)*mSubTickCount);
5542 if (mSubTickCount > 0)
5542 if (mSubTickCount > 0)
5543 {
5543 {
5544 double subTickStep = 0;
5544 double subTickStep = 0;
5545 double subTickPosition = 0;
5545 double subTickPosition = 0;
5546 int subTickIndex = 0;
5546 int subTickIndex = 0;
5547 bool done = false;
5547 bool done = false;
5548 int lowTick = mLowestVisibleTick > 0 ? mLowestVisibleTick-1 : mLowestVisibleTick;
5548 int lowTick = mLowestVisibleTick > 0 ? mLowestVisibleTick-1 : mLowestVisibleTick;
5549 int highTick = mHighestVisibleTick < mTickVector.size()-1 ? mHighestVisibleTick+1 : mHighestVisibleTick;
5549 int highTick = mHighestVisibleTick < mTickVector.size()-1 ? mHighestVisibleTick+1 : mHighestVisibleTick;
5550 for (int i=lowTick+1; i<=highTick; ++i)
5550 for (int i=lowTick+1; i<=highTick; ++i)
5551 {
5551 {
5552 subTickStep = (mTickVector.at(i)-mTickVector.at(i-1))/(double)(mSubTickCount+1);
5552 subTickStep = (mTickVector.at(i)-mTickVector.at(i-1))/(double)(mSubTickCount+1);
5553 for (int k=1; k<=mSubTickCount; ++k)
5553 for (int k=1; k<=mSubTickCount; ++k)
5554 {
5554 {
5555 subTickPosition = mTickVector.at(i-1) + k*subTickStep;
5555 subTickPosition = mTickVector.at(i-1) + k*subTickStep;
5556 if (subTickPosition < mRange.lower)
5556 if (subTickPosition < mRange.lower)
5557 continue;
5557 continue;
5558 if (subTickPosition > mRange.upper)
5558 if (subTickPosition > mRange.upper)
5559 {
5559 {
5560 done = true;
5560 done = true;
5561 break;
5561 break;
5562 }
5562 }
5563 mSubTickVector[subTickIndex] = subTickPosition;
5563 mSubTickVector[subTickIndex] = subTickPosition;
5564 subTickIndex++;
5564 subTickIndex++;
5565 }
5565 }
5566 if (done) break;
5566 if (done) break;
5567 }
5567 }
5568 mSubTickVector.resize(subTickIndex);
5568 mSubTickVector.resize(subTickIndex);
5569 }
5569 }
5570
5570
5571 // generate tick labels according to tick positions:
5571 // generate tick labels according to tick positions:
5572 if (mAutoTickLabels)
5572 if (mAutoTickLabels)
5573 {
5573 {
5574 int vecsize = mTickVector.size();
5574 int vecsize = mTickVector.size();
5575 mTickVectorLabels.resize(vecsize);
5575 mTickVectorLabels.resize(vecsize);
5576 if (mTickLabelType == ltNumber)
5576 if (mTickLabelType == ltNumber)
5577 {
5577 {
5578 for (int i=mLowestVisibleTick; i<=mHighestVisibleTick; ++i)
5578 for (int i=mLowestVisibleTick; i<=mHighestVisibleTick; ++i)
5579 mTickVectorLabels[i] = mParentPlot->locale().toString(mTickVector.at(i), mNumberFormatChar.toLatin1(), mNumberPrecision);
5579 mTickVectorLabels[i] = mParentPlot->locale().toString(mTickVector.at(i), mNumberFormatChar.toLatin1(), mNumberPrecision);
5580 } else if (mTickLabelType == ltDateTime)
5580 } else if (mTickLabelType == ltDateTime)
5581 {
5581 {
5582 for (int i=mLowestVisibleTick; i<=mHighestVisibleTick; ++i)
5582 for (int i=mLowestVisibleTick; i<=mHighestVisibleTick; ++i)
5583 {
5583 {
5584 #if QT_VERSION < QT_VERSION_CHECK(4, 7, 0) // use fromMSecsSinceEpoch function if available, to gain sub-second accuracy on tick labels (e.g. for format "hh:mm:ss:zzz")
5584 #if QT_VERSION < QT_VERSION_CHECK(4, 7, 0) // use fromMSecsSinceEpoch function if available, to gain sub-second accuracy on tick labels (e.g. for format "hh:mm:ss:zzz")
5585 mTickVectorLabels[i] = mParentPlot->locale().toString(QDateTime::fromTime_t(mTickVector.at(i)).toTimeSpec(mDateTimeSpec), mDateTimeFormat);
5585 mTickVectorLabels[i] = mParentPlot->locale().toString(QDateTime::fromTime_t(mTickVector.at(i)).toTimeSpec(mDateTimeSpec), mDateTimeFormat);
5586 #else
5586 #else
5587 mTickVectorLabels[i] = mParentPlot->locale().toString(QDateTime::fromMSecsSinceEpoch(mTickVector.at(i)*1000).toTimeSpec(mDateTimeSpec), mDateTimeFormat);
5587 mTickVectorLabels[i] = mParentPlot->locale().toString(QDateTime::fromMSecsSinceEpoch(mTickVector.at(i)*1000).toTimeSpec(mDateTimeSpec), mDateTimeFormat);
5588 #endif
5588 #endif
5589 }
5589 }
5590 }
5590 }
5591 } else // mAutoTickLabels == false
5591 } else // mAutoTickLabels == false
5592 {
5592 {
5593 if (mAutoTicks) // ticks generated automatically, but not ticklabels, so emit ticksRequest here for labels
5593 if (mAutoTicks) // ticks generated automatically, but not ticklabels, so emit ticksRequest here for labels
5594 {
5594 {
5595 emit ticksRequest();
5595 emit ticksRequest();
5596 }
5596 }
5597 // make sure provided tick label vector has correct (minimal) length:
5597 // make sure provided tick label vector has correct (minimal) length:
5598 if (mTickVectorLabels.size() < mTickVector.size())
5598 if (mTickVectorLabels.size() < mTickVector.size())
5599 mTickVectorLabels.resize(mTickVector.size());
5599 mTickVectorLabels.resize(mTickVector.size());
5600 }
5600 }
5601 }
5601 }
5602
5602
@@ -5611,63 +5611,63 void QCPAxis::setupTickVectors()
5611 */
5611 */
5612 void QCPAxis::generateAutoTicks()
5612 void QCPAxis::generateAutoTicks()
5613 {
5613 {
5614 if (mScaleType == stLinear)
5614 if (mScaleType == stLinear)
5615 {
5615 {
5616 if (mAutoTickStep)
5616 if (mAutoTickStep)
5617 {
5617 {
5618 // Generate tick positions according to linear scaling:
5618 // Generate tick positions according to linear scaling:
5619 mTickStep = mRange.size()/(double)(mAutoTickCount+1e-10); // mAutoTickCount ticks on average, the small addition is to prevent jitter on exact integers
5619 mTickStep = mRange.size()/(double)(mAutoTickCount+1e-10); // mAutoTickCount ticks on average, the small addition is to prevent jitter on exact integers
5620 double magnitudeFactor = qPow(10.0, qFloor(qLn(mTickStep)/qLn(10.0))); // get magnitude factor e.g. 0.01, 1, 10, 1000 etc.
5620 double magnitudeFactor = qPow(10.0, qFloor(qLn(mTickStep)/qLn(10.0))); // get magnitude factor e.g. 0.01, 1, 10, 1000 etc.
5621 double tickStepMantissa = mTickStep/magnitudeFactor;
5621 double tickStepMantissa = mTickStep/magnitudeFactor;
5622 if (tickStepMantissa < 5)
5622 if (tickStepMantissa < 5)
5623 {
5623 {
5624 // round digit after decimal point to 0.5
5624 // round digit after decimal point to 0.5
5625 mTickStep = (int)(tickStepMantissa*2)/2.0*magnitudeFactor;
5625 mTickStep = (int)(tickStepMantissa*2)/2.0*magnitudeFactor;
5626 } else
5626 } else
5627 {
5627 {
5628 // round to first digit in multiples of 2
5628 // round to first digit in multiples of 2
5629 mTickStep = (int)(tickStepMantissa/2.0)*2.0*magnitudeFactor;
5629 mTickStep = (int)(tickStepMantissa/2.0)*2.0*magnitudeFactor;
5630 }
5630 }
5631 }
5631 }
5632 if (mAutoSubTicks)
5632 if (mAutoSubTicks)
5633 mSubTickCount = calculateAutoSubTickCount(mTickStep);
5633 mSubTickCount = calculateAutoSubTickCount(mTickStep);
5634 // Generate tick positions according to mTickStep:
5634 // Generate tick positions according to mTickStep:
5635 qint64 firstStep = floor(mRange.lower/mTickStep); // do not use qFloor here, or we'll lose 64 bit precision
5635 qint64 firstStep = floor(mRange.lower/mTickStep); // do not use qFloor here, or we'll lose 64 bit precision
5636 qint64 lastStep = ceil(mRange.upper/mTickStep); // do not use qCeil here, or we'll lose 64 bit precision
5636 qint64 lastStep = ceil(mRange.upper/mTickStep); // do not use qCeil here, or we'll lose 64 bit precision
5637 int tickcount = lastStep-firstStep+1;
5637 int tickcount = lastStep-firstStep+1;
5638 if (tickcount < 0) tickcount = 0;
5638 if (tickcount < 0) tickcount = 0;
5639 mTickVector.resize(tickcount);
5639 mTickVector.resize(tickcount);
5640 for (int i=0; i<tickcount; ++i)
5640 for (int i=0; i<tickcount; ++i)
5641 mTickVector[i] = (firstStep+i)*mTickStep;
5641 mTickVector[i] = (firstStep+i)*mTickStep;
5642 } else // mScaleType == stLogarithmic
5642 } else // mScaleType == stLogarithmic
5643 {
5643 {
5644 // Generate tick positions according to logbase scaling:
5644 // Generate tick positions according to logbase scaling:
5645 if (mRange.lower > 0 && mRange.upper > 0) // positive range
5645 if (mRange.lower > 0 && mRange.upper > 0) // positive range
5646 {
5646 {
5647 double lowerMag = basePow(qFloor(baseLog(mRange.lower)));
5647 double lowerMag = basePow(qFloor(baseLog(mRange.lower)));
5648 double currentMag = lowerMag;
5648 double currentMag = lowerMag;
5649 mTickVector.clear();
5649 mTickVector.clear();
5650 mTickVector.append(currentMag);
5650 mTickVector.append(currentMag);
5651 while (currentMag < mRange.upper && currentMag > 0) // currentMag might be zero for ranges ~1e-300, just cancel in that case
5651 while (currentMag < mRange.upper && currentMag > 0) // currentMag might be zero for ranges ~1e-300, just cancel in that case
5652 {
5652 {
5653 currentMag *= mScaleLogBase;
5653 currentMag *= mScaleLogBase;
5654 mTickVector.append(currentMag);
5654 mTickVector.append(currentMag);
5655 }
5655 }
5656 } else if (mRange.lower < 0 && mRange.upper < 0) // negative range
5656 } else if (mRange.lower < 0 && mRange.upper < 0) // negative range
5657 {
5657 {
5658 double lowerMag = -basePow(qCeil(baseLog(-mRange.lower)));
5658 double lowerMag = -basePow(qCeil(baseLog(-mRange.lower)));
5659 double currentMag = lowerMag;
5659 double currentMag = lowerMag;
5660 mTickVector.clear();
5660 mTickVector.clear();
5661 mTickVector.append(currentMag);
5661 mTickVector.append(currentMag);
5662 while (currentMag < mRange.upper && currentMag < 0) // currentMag might be zero for ranges ~1e-300, just cancel in that case
5662 while (currentMag < mRange.upper && currentMag < 0) // currentMag might be zero for ranges ~1e-300, just cancel in that case
5663 {
5663 {
5664 currentMag /= mScaleLogBase;
5664 currentMag /= mScaleLogBase;
5665 mTickVector.append(currentMag);
5665 mTickVector.append(currentMag);
5666 }
5666 }
5667 } else // invalid range for logarithmic scale, because lower and upper have different sign
5667 } else // invalid range for logarithmic scale, because lower and upper have different sign
5668 {
5668 {
5669 mTickVector.clear();
5669 mTickVector.clear();
5670 qDebug() << Q_FUNC_INFO << "Invalid range for logarithmic plot: " << mRange.lower << "-" << mRange.upper;
5670 qDebug() << Q_FUNC_INFO << "Invalid range for logarithmic plot: " << mRange.lower << "-" << mRange.upper;
5671 }
5671 }
5672 }
5672 }
5673 }
5673 }
@@ -5687,25 +5687,25 void QCPAxis::generateAutoTicks()
5687 */
5687 */
5688 int QCPAxis::calculateAutoSubTickCount(double tickStep) const
5688 int QCPAxis::calculateAutoSubTickCount(double tickStep) const
5689 {
5689 {
5690 int result = mSubTickCount; // default to current setting, if no proper value can be found
5690 int result = mSubTickCount; // default to current setting, if no proper value can be found
5691
5691
5692 // get mantissa of tickstep:
5692 // get mantissa of tickstep:
5693 double magnitudeFactor = qPow(10.0, qFloor(qLn(tickStep)/qLn(10.0))); // get magnitude factor e.g. 0.01, 1, 10, 1000 etc.
5693 double magnitudeFactor = qPow(10.0, qFloor(qLn(tickStep)/qLn(10.0))); // get magnitude factor e.g. 0.01, 1, 10, 1000 etc.
5694 double tickStepMantissa = tickStep/magnitudeFactor;
5694 double tickStepMantissa = tickStep/magnitudeFactor;
5695
5695
5696 // separate integer and fractional part of mantissa:
5696 // separate integer and fractional part of mantissa:
5697 double epsilon = 0.01;
5697 double epsilon = 0.01;
5698 double intPartf;
5698 double intPartf;
5699 int intPart;
5699 int intPart;
5700 double fracPart = modf(tickStepMantissa, &intPartf);
5700 double fracPart = modf(tickStepMantissa, &intPartf);
5701 intPart = intPartf;
5701 intPart = intPartf;
5702
5702
5703 // handle cases with (almost) integer mantissa:
5703 // handle cases with (almost) integer mantissa:
5704 if (fracPart < epsilon || 1.0-fracPart < epsilon)
5704 if (fracPart < epsilon || 1.0-fracPart < epsilon)
5705 {
5705 {
5706 if (1.0-fracPart < epsilon)
5706 if (1.0-fracPart < epsilon)
5707 ++intPart;
5707 ++intPart;
5708 switch (intPart)
5708 switch (intPart)
5709 {
5709 {
5710 case 1: result = 4; break; // 1.0 -> 0.2 substep
5710 case 1: result = 4; break; // 1.0 -> 0.2 substep
5711 case 2: result = 3; break; // 2.0 -> 0.5 substep
5711 case 2: result = 3; break; // 2.0 -> 0.5 substep
@@ -5719,10 +5719,10 int QCPAxis::calculateAutoSubTickCount(d
5719 }
5719 }
5720 } else
5720 } else
5721 {
5721 {
5722 // handle cases with significantly fractional mantissa:
5722 // handle cases with significantly fractional mantissa:
5723 if (qAbs(fracPart-0.5) < epsilon) // *.5 mantissa
5723 if (qAbs(fracPart-0.5) < epsilon) // *.5 mantissa
5724 {
5724 {
5725 switch (intPart)
5725 switch (intPart)
5726 {
5726 {
5727 case 1: result = 2; break; // 1.5 -> 0.5 substep
5727 case 1: result = 2; break; // 1.5 -> 0.5 substep
5728 case 2: result = 4; break; // 2.5 -> 0.5 substep
5728 case 2: result = 4; break; // 2.5 -> 0.5 substep
@@ -5735,33 +5735,33 int QCPAxis::calculateAutoSubTickCount(d
5735 case 9: result = 4; break; // 9.5 -> 1.9 substep
5735 case 9: result = 4; break; // 9.5 -> 1.9 substep
5736 }
5736 }
5737 }
5737 }
5738 // if mantissa fraction isnt 0.0 or 0.5, don't bother finding good sub tick marks, leave default
5738 // if mantissa fraction isnt 0.0 or 0.5, don't bother finding good sub tick marks, leave default
5739 }
5739 }
5740
5740
5741 return result;
5741 return result;
5742 }
5742 }
5743
5743
5744 /* inherits documentation from base class */
5744 /* inherits documentation from base class */
5745 void QCPAxis::selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged)
5745 void QCPAxis::selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged)
5746 {
5746 {
5747 Q_UNUSED(event)
5747 Q_UNUSED(event)
5748 SelectablePart part = details.value<SelectablePart>();
5748 SelectablePart part = details.value<SelectablePart>();
5749 if (mSelectableParts.testFlag(part))
5749 if (mSelectableParts.testFlag(part))
5750 {
5750 {
5751 SelectableParts selBefore = mSelectedParts;
5751 SelectableParts selBefore = mSelectedParts;
5752 setSelectedParts(additive ? mSelectedParts^part : part);
5752 setSelectedParts(additive ? mSelectedParts^part : part);
5753 if (selectionStateChanged)
5753 if (selectionStateChanged)
5754 *selectionStateChanged = mSelectedParts != selBefore;
5754 *selectionStateChanged = mSelectedParts != selBefore;
5755 }
5755 }
5756 }
5756 }
5757
5757
5758 /* inherits documentation from base class */
5758 /* inherits documentation from base class */
5759 void QCPAxis::deselectEvent(bool *selectionStateChanged)
5759 void QCPAxis::deselectEvent(bool *selectionStateChanged)
5760 {
5760 {
5761 SelectableParts selBefore = mSelectedParts;
5761 SelectableParts selBefore = mSelectedParts;
5762 setSelectedParts(mSelectedParts & ~mSelectableParts);
5762 setSelectedParts(mSelectedParts & ~mSelectableParts);
5763 if (selectionStateChanged)
5763 if (selectionStateChanged)
5764 *selectionStateChanged = mSelectedParts != selBefore;
5764 *selectionStateChanged = mSelectedParts != selBefore;
5765 }
5765 }
5766
5766
5767 /*! \internal
5767 /*! \internal
@@ -5779,7 +5779,7 void QCPAxis::deselectEvent(bool *select
5779 */
5779 */
5780 void QCPAxis::applyDefaultAntialiasingHint(QCPPainter *painter) const
5780 void QCPAxis::applyDefaultAntialiasingHint(QCPPainter *painter) const
5781 {
5781 {
5782 applyAntialiasingHint(painter, mAntialiased, QCP::aeAxes);
5782 applyAntialiasingHint(painter, mAntialiased, QCP::aeAxes);
5783 }
5783 }
5784
5784
5785 /*! \internal
5785 /*! \internal
@@ -5789,51 +5789,51 void QCPAxis::applyDefaultAntialiasingHi
5789 */
5789 */
5790 void QCPAxis::draw(QCPPainter *painter)
5790 void QCPAxis::draw(QCPPainter *painter)
5791 {
5791 {
5792 const int lowTick = mLowestVisibleTick;
5792 const int lowTick = mLowestVisibleTick;
5793 const int highTick = mHighestVisibleTick;
5793 const int highTick = mHighestVisibleTick;
5794 QVector<double> subTickPositions; // the final coordToPixel transformed vector passed to QCPAxisPainter
5794 QVector<double> subTickPositions; // the final coordToPixel transformed vector passed to QCPAxisPainter
5795 QVector<double> tickPositions; // the final coordToPixel transformed vector passed to QCPAxisPainter
5795 QVector<double> tickPositions; // the final coordToPixel transformed vector passed to QCPAxisPainter
5796 QVector<QString> tickLabels; // the final vector passed to QCPAxisPainter
5796 QVector<QString> tickLabels; // the final vector passed to QCPAxisPainter
5797 tickPositions.reserve(highTick-lowTick+1);
5797 tickPositions.reserve(highTick-lowTick+1);
5798 tickLabels.reserve(highTick-lowTick+1);
5798 tickLabels.reserve(highTick-lowTick+1);
5799 subTickPositions.reserve(mSubTickVector.size());
5799 subTickPositions.reserve(mSubTickVector.size());
5800
5800
5801 if (mTicks)
5801 if (mTicks)
5802 {
5802 {
5803 for (int i=lowTick; i<=highTick; ++i)
5803 for (int i=lowTick; i<=highTick; ++i)
5804 {
5804 {
5805 tickPositions.append(coordToPixel(mTickVector.at(i)));
5805 tickPositions.append(coordToPixel(mTickVector.at(i)));
5806 if (mTickLabels)
5806 if (mTickLabels)
5807 tickLabels.append(mTickVectorLabels.at(i));
5807 tickLabels.append(mTickVectorLabels.at(i));
5808 }
5808 }
5809
5809
5810 if (mSubTickCount > 0)
5810 if (mSubTickCount > 0)
5811 {
5811 {
5812 const int subTickCount = mSubTickVector.size();
5812 const int subTickCount = mSubTickVector.size();
5813 for (int i=0; i<subTickCount; ++i) // no need to check bounds because subticks are always only created inside current mRange
5813 for (int i=0; i<subTickCount; ++i) // no need to check bounds because subticks are always only created inside current mRange
5814 subTickPositions.append(coordToPixel(mSubTickVector.at(i)));
5814 subTickPositions.append(coordToPixel(mSubTickVector.at(i)));
5815 }
5815 }
5816 }
5816 }
5817 // transfer all properties of this axis to QCPAxisPainterPrivate which it needs to draw the axis.
5817 // transfer all properties of this axis to QCPAxisPainterPrivate which it needs to draw the axis.
5818 // Note that some axis painter properties are already set by direct feed-through with QCPAxis setters
5818 // Note that some axis painter properties are already set by direct feed-through with QCPAxis setters
5819 mAxisPainter->type = mAxisType;
5819 mAxisPainter->type = mAxisType;
5820 mAxisPainter->basePen = getBasePen();
5820 mAxisPainter->basePen = getBasePen();
5821 mAxisPainter->labelFont = getLabelFont();
5821 mAxisPainter->labelFont = getLabelFont();
5822 mAxisPainter->labelColor = getLabelColor();
5822 mAxisPainter->labelColor = getLabelColor();
5823 mAxisPainter->label = mLabel;
5823 mAxisPainter->label = mLabel;
5824 mAxisPainter->substituteExponent = mAutoTickLabels && mNumberBeautifulPowers && mTickLabelType == ltNumber;
5824 mAxisPainter->substituteExponent = mAutoTickLabels && mNumberBeautifulPowers && mTickLabelType == ltNumber;
5825 mAxisPainter->tickPen = getTickPen();
5825 mAxisPainter->tickPen = getTickPen();
5826 mAxisPainter->subTickPen = getSubTickPen();
5826 mAxisPainter->subTickPen = getSubTickPen();
5827 mAxisPainter->tickLabelFont = getTickLabelFont();
5827 mAxisPainter->tickLabelFont = getTickLabelFont();
5828 mAxisPainter->tickLabelColor = getTickLabelColor();
5828 mAxisPainter->tickLabelColor = getTickLabelColor();
5829 mAxisPainter->axisRect = mAxisRect->rect();
5829 mAxisPainter->axisRect = mAxisRect->rect();
5830 mAxisPainter->viewportRect = mParentPlot->viewport();
5830 mAxisPainter->viewportRect = mParentPlot->viewport();
5831 mAxisPainter->abbreviateDecimalPowers = mScaleType == stLogarithmic;
5831 mAxisPainter->abbreviateDecimalPowers = mScaleType == stLogarithmic;
5832 mAxisPainter->reversedEndings = mRangeReversed;
5832 mAxisPainter->reversedEndings = mRangeReversed;
5833 mAxisPainter->tickPositions = tickPositions;
5833 mAxisPainter->tickPositions = tickPositions;
5834 mAxisPainter->tickLabels = tickLabels;
5834 mAxisPainter->tickLabels = tickLabels;
5835 mAxisPainter->subTickPositions = subTickPositions;
5835 mAxisPainter->subTickPositions = subTickPositions;
5836 mAxisPainter->draw(painter);
5836 mAxisPainter->draw(painter);
5837 }
5837 }
5838
5838
5839 /*! \internal
5839 /*! \internal
@@ -5854,34 +5854,34 void QCPAxis::draw(QCPPainter *painter)
5854 */
5854 */
5855 void QCPAxis::visibleTickBounds(int &lowIndex, int &highIndex) const
5855 void QCPAxis::visibleTickBounds(int &lowIndex, int &highIndex) const
5856 {
5856 {
5857 bool lowFound = false;
5857 bool lowFound = false;
5858 bool highFound = false;
5858 bool highFound = false;
5859 lowIndex = 0;
5859 lowIndex = 0;
5860 highIndex = -1;
5860 highIndex = -1;
5861
5861
5862 for (int i=0; i < mTickVector.size(); ++i)
5862 for (int i=0; i < mTickVector.size(); ++i)
5863 {
5863 {
5864 if (mTickVector.at(i) >= mRange.lower)
5864 if (mTickVector.at(i) >= mRange.lower)
5865 {
5865 {
5866 lowFound = true;
5866 lowFound = true;
5867 lowIndex = i;
5867 lowIndex = i;
5868 break;
5868 break;
5869 }
5869 }
5870 }
5870 }
5871 for (int i=mTickVector.size()-1; i >= 0; --i)
5871 for (int i=mTickVector.size()-1; i >= 0; --i)
5872 {
5872 {
5873 if (mTickVector.at(i) <= mRange.upper)
5873 if (mTickVector.at(i) <= mRange.upper)
5874 {
5874 {
5875 highFound = true;
5875 highFound = true;
5876 highIndex = i;
5876 highIndex = i;
5877 break;
5877 break;
5878 }
5878 }
5879 }
5879 }
5880
5880
5881 if (!lowFound && highFound)
5881 if (!lowFound && highFound)
5882 lowIndex = highIndex+1;
5882 lowIndex = highIndex+1;
5883 else if (lowFound && !highFound)
5883 else if (lowFound && !highFound)
5884 highIndex = lowIndex-1;
5884 highIndex = lowIndex-1;
5885 }
5885 }
5886
5886
5887 /*! \internal
5887 /*! \internal
@@ -5894,7 +5894,7 void QCPAxis::visibleTickBounds(int &low
5894 */
5894 */
5895 double QCPAxis::baseLog(double value) const
5895 double QCPAxis::baseLog(double value) const
5896 {
5896 {
5897 return qLn(value)*mScaleLogBaseLogInv;
5897 return qLn(value)*mScaleLogBaseLogInv;
5898 }
5898 }
5899
5899
5900 /*! \internal
5900 /*! \internal
@@ -5906,7 +5906,7 double QCPAxis::baseLog(double value) co
5906 */
5906 */
5907 double QCPAxis::basePow(double value) const
5907 double QCPAxis::basePow(double value) const
5908 {
5908 {
5909 return qPow(mScaleLogBase, value);
5909 return qPow(mScaleLogBase, value);
5910 }
5910 }
5911
5911
5912 /*! \internal
5912 /*! \internal
@@ -5916,7 +5916,7 double QCPAxis::basePow(double value) co
5916 */
5916 */
5917 QPen QCPAxis::getBasePen() const
5917 QPen QCPAxis::getBasePen() const
5918 {
5918 {
5919 return mSelectedParts.testFlag(spAxis) ? mSelectedBasePen : mBasePen;
5919 return mSelectedParts.testFlag(spAxis) ? mSelectedBasePen : mBasePen;
5920 }
5920 }
5921
5921
5922 /*! \internal
5922 /*! \internal
@@ -5926,7 +5926,7 QPen QCPAxis::getBasePen() const
5926 */
5926 */
5927 QPen QCPAxis::getTickPen() const
5927 QPen QCPAxis::getTickPen() const
5928 {
5928 {
5929 return mSelectedParts.testFlag(spAxis) ? mSelectedTickPen : mTickPen;
5929 return mSelectedParts.testFlag(spAxis) ? mSelectedTickPen : mTickPen;
5930 }
5930 }
5931
5931
5932 /*! \internal
5932 /*! \internal
@@ -5936,7 +5936,7 QPen QCPAxis::getTickPen() const
5936 */
5936 */
5937 QPen QCPAxis::getSubTickPen() const
5937 QPen QCPAxis::getSubTickPen() const
5938 {
5938 {
5939 return mSelectedParts.testFlag(spAxis) ? mSelectedSubTickPen : mSubTickPen;
5939 return mSelectedParts.testFlag(spAxis) ? mSelectedSubTickPen : mSubTickPen;
5940 }
5940 }
5941
5941
5942 /*! \internal
5942 /*! \internal
@@ -5946,7 +5946,7 QPen QCPAxis::getSubTickPen() const
5946 */
5946 */
5947 QFont QCPAxis::getTickLabelFont() const
5947 QFont QCPAxis::getTickLabelFont() const
5948 {
5948 {
5949 return mSelectedParts.testFlag(spTickLabels) ? mSelectedTickLabelFont : mTickLabelFont;
5949 return mSelectedParts.testFlag(spTickLabels) ? mSelectedTickLabelFont : mTickLabelFont;
5950 }
5950 }
5951
5951
5952 /*! \internal
5952 /*! \internal
@@ -5956,7 +5956,7 QFont QCPAxis::getTickLabelFont() const
5956 */
5956 */
5957 QFont QCPAxis::getLabelFont() const
5957 QFont QCPAxis::getLabelFont() const
5958 {
5958 {
5959 return mSelectedParts.testFlag(spAxisLabel) ? mSelectedLabelFont : mLabelFont;
5959 return mSelectedParts.testFlag(spAxisLabel) ? mSelectedLabelFont : mLabelFont;
5960 }
5960 }
5961
5961
5962 /*! \internal
5962 /*! \internal
@@ -5966,7 +5966,7 QFont QCPAxis::getLabelFont() const
5966 */
5966 */
5967 QColor QCPAxis::getTickLabelColor() const
5967 QColor QCPAxis::getTickLabelColor() const
5968 {
5968 {
5969 return mSelectedParts.testFlag(spTickLabels) ? mSelectedTickLabelColor : mTickLabelColor;
5969 return mSelectedParts.testFlag(spTickLabels) ? mSelectedTickLabelColor : mTickLabelColor;
5970 }
5970 }
5971
5971
5972 /*! \internal
5972 /*! \internal
@@ -5976,7 +5976,7 QColor QCPAxis::getTickLabelColor() cons
5976 */
5976 */
5977 QColor QCPAxis::getLabelColor() const
5977 QColor QCPAxis::getLabelColor() const
5978 {
5978 {
5979 return mSelectedParts.testFlag(spAxisLabel) ? mSelectedLabelColor : mLabelColor;
5979 return mSelectedParts.testFlag(spAxisLabel) ? mSelectedLabelColor : mLabelColor;
5980 }
5980 }
5981
5981
5982 /*! \internal
5982 /*! \internal
@@ -5995,52 +5995,52 QColor QCPAxis::getLabelColor() const
5995 */
5995 */
5996 int QCPAxis::calculateMargin()
5996 int QCPAxis::calculateMargin()
5997 {
5997 {
5998 if (!mVisible) // if not visible, directly return 0, don't cache 0 because we can't react to setVisible in QCPAxis
5998 if (!mVisible) // if not visible, directly return 0, don't cache 0 because we can't react to setVisible in QCPAxis
5999 return 0;
5999 return 0;
6000
6000
6001 if (mCachedMarginValid)
6001 if (mCachedMarginValid)
6002 return mCachedMargin;
6002 return mCachedMargin;
6003
6003
6004 // run through similar steps as QCPAxis::draw, and caluclate margin needed to fit axis and its labels
6004 // run through similar steps as QCPAxis::draw, and caluclate margin needed to fit axis and its labels
6005 int margin = 0;
6005 int margin = 0;
6006
6006
6007 int lowTick, highTick;
6007 int lowTick, highTick;
6008 visibleTickBounds(lowTick, highTick);
6008 visibleTickBounds(lowTick, highTick);
6009 QVector<double> tickPositions; // the final coordToPixel transformed vector passed to QCPAxisPainter
6009 QVector<double> tickPositions; // the final coordToPixel transformed vector passed to QCPAxisPainter
6010 QVector<QString> tickLabels; // the final vector passed to QCPAxisPainter
6010 QVector<QString> tickLabels; // the final vector passed to QCPAxisPainter
6011 tickPositions.reserve(highTick-lowTick+1);
6011 tickPositions.reserve(highTick-lowTick+1);
6012 tickLabels.reserve(highTick-lowTick+1);
6012 tickLabels.reserve(highTick-lowTick+1);
6013 if (mTicks)
6013 if (mTicks)
6014 {
6014 {
6015 for (int i=lowTick; i<=highTick; ++i)
6015 for (int i=lowTick; i<=highTick; ++i)
6016 {
6016 {
6017 tickPositions.append(coordToPixel(mTickVector.at(i)));
6017 tickPositions.append(coordToPixel(mTickVector.at(i)));
6018 if (mTickLabels)
6018 if (mTickLabels)
6019 tickLabels.append(mTickVectorLabels.at(i));
6019 tickLabels.append(mTickVectorLabels.at(i));
6020 }
6020 }
6021 }
6021 }
6022 // transfer all properties of this axis to QCPAxisPainterPrivate which it needs to calculate the size.
6022 // transfer all properties of this axis to QCPAxisPainterPrivate which it needs to calculate the size.
6023 // Note that some axis painter properties are already set by direct feed-through with QCPAxis setters
6023 // Note that some axis painter properties are already set by direct feed-through with QCPAxis setters
6024 mAxisPainter->type = mAxisType;
6024 mAxisPainter->type = mAxisType;
6025 mAxisPainter->labelFont = getLabelFont();
6025 mAxisPainter->labelFont = getLabelFont();
6026 mAxisPainter->label = mLabel;
6026 mAxisPainter->label = mLabel;
6027 mAxisPainter->tickLabelFont = mTickLabelFont;
6027 mAxisPainter->tickLabelFont = mTickLabelFont;
6028 mAxisPainter->axisRect = mAxisRect->rect();
6028 mAxisPainter->axisRect = mAxisRect->rect();
6029 mAxisPainter->viewportRect = mParentPlot->viewport();
6029 mAxisPainter->viewportRect = mParentPlot->viewport();
6030 mAxisPainter->tickPositions = tickPositions;
6030 mAxisPainter->tickPositions = tickPositions;
6031 mAxisPainter->tickLabels = tickLabels;
6031 mAxisPainter->tickLabels = tickLabels;
6032 margin += mAxisPainter->size();
6032 margin += mAxisPainter->size();
6033 margin += mPadding;
6033 margin += mPadding;
6034
6034
6035 mCachedMargin = margin;
6035 mCachedMargin = margin;
6036 mCachedMarginValid = true;
6036 mCachedMarginValid = true;
6037 return margin;
6037 return margin;
6038 }
6038 }
6039
6039
6040 /* inherits documentation from base class */
6040 /* inherits documentation from base class */
6041 QCP::Interaction QCPAxis::selectionCategory() const
6041 QCP::Interaction QCPAxis::selectionCategory() const
6042 {
6042 {
6043 return QCP::iSelectAxes;
6043 return QCP::iSelectAxes;
6044 }
6044 }
6045
6045
6046
6046
@@ -6065,27 +6065,27 QCP::Interaction QCPAxis::selectionCateg
6065 redraw, to utilize the caching mechanisms.
6065 redraw, to utilize the caching mechanisms.
6066 */
6066 */
6067 QCPAxisPainterPrivate::QCPAxisPainterPrivate(QCustomPlot *parentPlot) :
6067 QCPAxisPainterPrivate::QCPAxisPainterPrivate(QCustomPlot *parentPlot) :
6068 type(QCPAxis::atLeft),
6068 type(QCPAxis::atLeft),
6069 basePen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)),
6069 basePen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)),
6070 lowerEnding(QCPLineEnding::esNone),
6070 lowerEnding(QCPLineEnding::esNone),
6071 upperEnding(QCPLineEnding::esNone),
6071 upperEnding(QCPLineEnding::esNone),
6072 labelPadding(0),
6072 labelPadding(0),
6073 tickLabelPadding(0),
6073 tickLabelPadding(0),
6074 tickLabelRotation(0),
6074 tickLabelRotation(0),
6075 tickLabelSide(QCPAxis::lsOutside),
6075 tickLabelSide(QCPAxis::lsOutside),
6076 substituteExponent(true),
6076 substituteExponent(true),
6077 numberMultiplyCross(false),
6077 numberMultiplyCross(false),
6078 tickLengthIn(5),
6078 tickLengthIn(5),
6079 tickLengthOut(0),
6079 tickLengthOut(0),
6080 subTickLengthIn(2),
6080 subTickLengthIn(2),
6081 subTickLengthOut(0),
6081 subTickLengthOut(0),
6082 tickPen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)),
6082 tickPen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)),
6083 subTickPen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)),
6083 subTickPen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)),
6084 offset(0),
6084 offset(0),
6085 abbreviateDecimalPowers(false),
6085 abbreviateDecimalPowers(false),
6086 reversedEndings(false),
6086 reversedEndings(false),
6087 mParentPlot(parentPlot),
6087 mParentPlot(parentPlot),
6088 mLabelCache(16) // cache at most 16 (tick) labels
6088 mLabelCache(16) // cache at most 16 (tick) labels
6089 {
6089 {
6090 }
6090 }
6091
6091
@@ -6102,15 +6102,15 QCPAxisPainterPrivate::~QCPAxisPainterPr
6102 */
6102 */
6103 void QCPAxisPainterPrivate::draw(QCPPainter *painter)
6103 void QCPAxisPainterPrivate::draw(QCPPainter *painter)
6104 {
6104 {
6105 QByteArray newHash = generateLabelParameterHash();
6105 QByteArray newHash = generateLabelParameterHash();
6106 if (newHash != mLabelParameterHash)
6106 if (newHash != mLabelParameterHash)
6107 {
6107 {
6108 mLabelCache.clear();
6108 mLabelCache.clear();
6109 mLabelParameterHash = newHash;
6109 mLabelParameterHash = newHash;
6110 }
6110 }
6111
6111
6112 QPoint origin;
6112 QPoint origin;
6113 switch (type)
6113 switch (type)
6114 {
6114 {
6115 case QCPAxis::atLeft: origin = axisRect.bottomLeft() +QPoint(-offset, 0); break;
6115 case QCPAxis::atLeft: origin = axisRect.bottomLeft() +QPoint(-offset, 0); break;
6116 case QCPAxis::atRight: origin = axisRect.bottomRight()+QPoint(+offset, 0); break;
6116 case QCPAxis::atRight: origin = axisRect.bottomRight()+QPoint(+offset, 0); break;
@@ -6118,175 +6118,175 void QCPAxisPainterPrivate::draw(QCPPain
6118 case QCPAxis::atBottom: origin = axisRect.bottomLeft() +QPoint(0, +offset); break;
6118 case QCPAxis::atBottom: origin = axisRect.bottomLeft() +QPoint(0, +offset); break;
6119 }
6119 }
6120
6120
6121 double xCor = 0, yCor = 0; // paint system correction, for pixel exact matches (affects baselines and ticks of top/right axes)
6121 double xCor = 0, yCor = 0; // paint system correction, for pixel exact matches (affects baselines and ticks of top/right axes)
6122 switch (type)
6122 switch (type)
6123 {
6123 {
6124 case QCPAxis::atTop: yCor = -1; break;
6124 case QCPAxis::atTop: yCor = -1; break;
6125 case QCPAxis::atRight: xCor = 1; break;
6125 case QCPAxis::atRight: xCor = 1; break;
6126 default: break;
6126 default: break;
6127 }
6127 }
6128
6128
6129 int margin = 0;
6129 int margin = 0;
6130 // draw baseline:
6130 // draw baseline:
6131 QLineF baseLine;
6131 QLineF baseLine;
6132 painter->setPen(basePen);
6132 painter->setPen(basePen);
6133 if (QCPAxis::orientation(type) == Qt::Horizontal)
6133 if (QCPAxis::orientation(type) == Qt::Horizontal)
6134 baseLine.setPoints(origin+QPointF(xCor, yCor), origin+QPointF(axisRect.width()+xCor, yCor));
6134 baseLine.setPoints(origin+QPointF(xCor, yCor), origin+QPointF(axisRect.width()+xCor, yCor));
6135 else
6135 else
6136 baseLine.setPoints(origin+QPointF(xCor, yCor), origin+QPointF(xCor, -axisRect.height()+yCor));
6136 baseLine.setPoints(origin+QPointF(xCor, yCor), origin+QPointF(xCor, -axisRect.height()+yCor));
6137 if (reversedEndings)
6137 if (reversedEndings)
6138 baseLine = QLineF(baseLine.p2(), baseLine.p1()); // won't make a difference for line itself, but for line endings later
6138 baseLine = QLineF(baseLine.p2(), baseLine.p1()); // won't make a difference for line itself, but for line endings later
6139 painter->drawLine(baseLine);
6139 painter->drawLine(baseLine);
6140
6140
6141 // draw ticks:
6141 // draw ticks:
6142 if (!tickPositions.isEmpty())
6142 if (!tickPositions.isEmpty())
6143 {
6143 {
6144 painter->setPen(tickPen);
6144 painter->setPen(tickPen);
6145 int tickDir = (type == QCPAxis::atBottom || type == QCPAxis::atRight) ? -1 : 1; // direction of ticks ("inward" is right for left axis and left for right axis)
6145 int tickDir = (type == QCPAxis::atBottom || type == QCPAxis::atRight) ? -1 : 1; // direction of ticks ("inward" is right for left axis and left for right axis)
6146 if (QCPAxis::orientation(type) == Qt::Horizontal)
6146 if (QCPAxis::orientation(type) == Qt::Horizontal)
6147 {
6147 {
6148 for (int i=0; i<tickPositions.size(); ++i)
6148 for (int i=0; i<tickPositions.size(); ++i)
6149 painter->drawLine(QLineF(tickPositions.at(i)+xCor, origin.y()-tickLengthOut*tickDir+yCor, tickPositions.at(i)+xCor, origin.y()+tickLengthIn*tickDir+yCor));
6149 painter->drawLine(QLineF(tickPositions.at(i)+xCor, origin.y()-tickLengthOut*tickDir+yCor, tickPositions.at(i)+xCor, origin.y()+tickLengthIn*tickDir+yCor));
6150 } else
6150 } else
6151 {
6151 {
6152 for (int i=0; i<tickPositions.size(); ++i)
6152 for (int i=0; i<tickPositions.size(); ++i)
6153 painter->drawLine(QLineF(origin.x()-tickLengthOut*tickDir+xCor, tickPositions.at(i)+yCor, origin.x()+tickLengthIn*tickDir+xCor, tickPositions.at(i)+yCor));
6153 painter->drawLine(QLineF(origin.x()-tickLengthOut*tickDir+xCor, tickPositions.at(i)+yCor, origin.x()+tickLengthIn*tickDir+xCor, tickPositions.at(i)+yCor));
6154 }
6154 }
6155 }
6155 }
6156
6156
6157 // draw subticks:
6157 // draw subticks:
6158 if (!subTickPositions.isEmpty())
6158 if (!subTickPositions.isEmpty())
6159 {
6159 {
6160 painter->setPen(subTickPen);
6160 painter->setPen(subTickPen);
6161 // direction of ticks ("inward" is right for left axis and left for right axis)
6161 // direction of ticks ("inward" is right for left axis and left for right axis)
6162 int tickDir = (type == QCPAxis::atBottom || type == QCPAxis::atRight) ? -1 : 1;
6162 int tickDir = (type == QCPAxis::atBottom || type == QCPAxis::atRight) ? -1 : 1;
6163 if (QCPAxis::orientation(type) == Qt::Horizontal)
6163 if (QCPAxis::orientation(type) == Qt::Horizontal)
6164 {
6164 {
6165 for (int i=0; i<subTickPositions.size(); ++i)
6165 for (int i=0; i<subTickPositions.size(); ++i)
6166 painter->drawLine(QLineF(subTickPositions.at(i)+xCor, origin.y()-subTickLengthOut*tickDir+yCor, subTickPositions.at(i)+xCor, origin.y()+subTickLengthIn*tickDir+yCor));
6166 painter->drawLine(QLineF(subTickPositions.at(i)+xCor, origin.y()-subTickLengthOut*tickDir+yCor, subTickPositions.at(i)+xCor, origin.y()+subTickLengthIn*tickDir+yCor));
6167 } else
6167 } else
6168 {
6168 {
6169 for (int i=0; i<subTickPositions.size(); ++i)
6169 for (int i=0; i<subTickPositions.size(); ++i)
6170 painter->drawLine(QLineF(origin.x()-subTickLengthOut*tickDir+xCor, subTickPositions.at(i)+yCor, origin.x()+subTickLengthIn*tickDir+xCor, subTickPositions.at(i)+yCor));
6170 painter->drawLine(QLineF(origin.x()-subTickLengthOut*tickDir+xCor, subTickPositions.at(i)+yCor, origin.x()+subTickLengthIn*tickDir+xCor, subTickPositions.at(i)+yCor));
6171 }
6171 }
6172 }
6172 }
6173 margin += qMax(0, qMax(tickLengthOut, subTickLengthOut));
6173 margin += qMax(0, qMax(tickLengthOut, subTickLengthOut));
6174
6174
6175 // draw axis base endings:
6175 // draw axis base endings:
6176 bool antialiasingBackup = painter->antialiasing();
6176 bool antialiasingBackup = painter->antialiasing();
6177 painter->setAntialiasing(true); // always want endings to be antialiased, even if base and ticks themselves aren't
6177 painter->setAntialiasing(true); // always want endings to be antialiased, even if base and ticks themselves aren't
6178 painter->setBrush(QBrush(basePen.color()));
6178 painter->setBrush(QBrush(basePen.color()));
6179 QVector2D baseLineVector(baseLine.dx(), baseLine.dy());
6179 QVector2D baseLineVector(baseLine.dx(), baseLine.dy());
6180 if (lowerEnding.style() != QCPLineEnding::esNone)
6180 if (lowerEnding.style() != QCPLineEnding::esNone)
6181 lowerEnding.draw(painter, QVector2D(baseLine.p1())-baseLineVector.normalized()*lowerEnding.realLength()*(lowerEnding.inverted()?-1:1), -baseLineVector);
6181 lowerEnding.draw(painter, QVector2D(baseLine.p1())-baseLineVector.normalized()*lowerEnding.realLength()*(lowerEnding.inverted()?-1:1), -baseLineVector);
6182 if (upperEnding.style() != QCPLineEnding::esNone)
6182 if (upperEnding.style() != QCPLineEnding::esNone)
6183 upperEnding.draw(painter, QVector2D(baseLine.p2())+baseLineVector.normalized()*upperEnding.realLength()*(upperEnding.inverted()?-1:1), baseLineVector);
6183 upperEnding.draw(painter, QVector2D(baseLine.p2())+baseLineVector.normalized()*upperEnding.realLength()*(upperEnding.inverted()?-1:1), baseLineVector);
6184 painter->setAntialiasing(antialiasingBackup);
6184 painter->setAntialiasing(antialiasingBackup);
6185
6185
6186 // tick labels:
6186 // tick labels:
6187 QRect oldClipRect;
6187 QRect oldClipRect;
6188 if (tickLabelSide == QCPAxis::lsInside) // if using inside labels, clip them to the axis rect
6188 if (tickLabelSide == QCPAxis::lsInside) // if using inside labels, clip them to the axis rect
6189 {
6189 {
6190 oldClipRect = painter->clipRegion().boundingRect();
6190 oldClipRect = painter->clipRegion().boundingRect();
6191 painter->setClipRect(axisRect);
6191 painter->setClipRect(axisRect);
6192 }
6192 }
6193 QSize tickLabelsSize(0, 0); // size of largest tick label, for offset calculation of axis label
6193 QSize tickLabelsSize(0, 0); // size of largest tick label, for offset calculation of axis label
6194 if (!tickLabels.isEmpty())
6194 if (!tickLabels.isEmpty())
6195 {
6195 {
6196 if (tickLabelSide == QCPAxis::lsOutside)
6196 if (tickLabelSide == QCPAxis::lsOutside)
6197 margin += tickLabelPadding;
6197 margin += tickLabelPadding;
6198 painter->setFont(tickLabelFont);
6198 painter->setFont(tickLabelFont);
6199 painter->setPen(QPen(tickLabelColor));
6199 painter->setPen(QPen(tickLabelColor));
6200 const int maxLabelIndex = qMin(tickPositions.size(), tickLabels.size());
6200 const int maxLabelIndex = qMin(tickPositions.size(), tickLabels.size());
6201 int distanceToAxis = margin;
6201 int distanceToAxis = margin;
6202 if (tickLabelSide == QCPAxis::lsInside)
6202 if (tickLabelSide == QCPAxis::lsInside)
6203 distanceToAxis = -(qMax(tickLengthIn, subTickLengthIn)+tickLabelPadding);
6203 distanceToAxis = -(qMax(tickLengthIn, subTickLengthIn)+tickLabelPadding);
6204 for (int i=0; i<maxLabelIndex; ++i)
6204 for (int i=0; i<maxLabelIndex; ++i)
6205 placeTickLabel(painter, tickPositions.at(i), distanceToAxis, tickLabels.at(i), &tickLabelsSize);
6205 placeTickLabel(painter, tickPositions.at(i), distanceToAxis, tickLabels.at(i), &tickLabelsSize);
6206 if (tickLabelSide == QCPAxis::lsOutside)
6206 if (tickLabelSide == QCPAxis::lsOutside)
6207 margin += (QCPAxis::orientation(type) == Qt::Horizontal) ? tickLabelsSize.height() : tickLabelsSize.width();
6207 margin += (QCPAxis::orientation(type) == Qt::Horizontal) ? tickLabelsSize.height() : tickLabelsSize.width();
6208 }
6208 }
6209 if (tickLabelSide == QCPAxis::lsInside)
6209 if (tickLabelSide == QCPAxis::lsInside)
6210 painter->setClipRect(oldClipRect);
6210 painter->setClipRect(oldClipRect);
6211
6211
6212 // axis label:
6212 // axis label:
6213 QRect labelBounds;
6213 QRect labelBounds;
6214 if (!label.isEmpty())
6214 if (!label.isEmpty())
6215 {
6215 {
6216 margin += labelPadding;
6216 margin += labelPadding;
6217 painter->setFont(labelFont);
6217 painter->setFont(labelFont);
6218 painter->setPen(QPen(labelColor));
6218 painter->setPen(QPen(labelColor));
6219 labelBounds = painter->fontMetrics().boundingRect(0, 0, 0, 0, Qt::TextDontClip, label);
6219 labelBounds = painter->fontMetrics().boundingRect(0, 0, 0, 0, Qt::TextDontClip, label);
6220 if (type == QCPAxis::atLeft)
6220 if (type == QCPAxis::atLeft)
6221 {
6221 {
6222 QTransform oldTransform = painter->transform();
6222 QTransform oldTransform = painter->transform();
6223 painter->translate((origin.x()-margin-labelBounds.height()), origin.y());
6223 painter->translate((origin.x()-margin-labelBounds.height()), origin.y());
6224 painter->rotate(-90);
6224 painter->rotate(-90);
6225 painter->drawText(0, 0, axisRect.height(), labelBounds.height(), Qt::TextDontClip | Qt::AlignCenter, label);
6225 painter->drawText(0, 0, axisRect.height(), labelBounds.height(), Qt::TextDontClip | Qt::AlignCenter, label);
6226 painter->setTransform(oldTransform);
6226 painter->setTransform(oldTransform);
6227 }
6227 }
6228 else if (type == QCPAxis::atRight)
6228 else if (type == QCPAxis::atRight)
6229 {
6229 {
6230 QTransform oldTransform = painter->transform();
6230 QTransform oldTransform = painter->transform();
6231 painter->translate((origin.x()+margin+labelBounds.height()), origin.y()-axisRect.height());
6231 painter->translate((origin.x()+margin+labelBounds.height()), origin.y()-axisRect.height());
6232 painter->rotate(90);
6232 painter->rotate(90);
6233 painter->drawText(0, 0, axisRect.height(), labelBounds.height(), Qt::TextDontClip | Qt::AlignCenter, label);
6233 painter->drawText(0, 0, axisRect.height(), labelBounds.height(), Qt::TextDontClip | Qt::AlignCenter, label);
6234 painter->setTransform(oldTransform);
6234 painter->setTransform(oldTransform);
6235 }
6235 }
6236 else if (type == QCPAxis::atTop)
6236 else if (type == QCPAxis::atTop)
6237 painter->drawText(origin.x(), origin.y()-margin-labelBounds.height(), axisRect.width(), labelBounds.height(), Qt::TextDontClip | Qt::AlignCenter, label);
6237 painter->drawText(origin.x(), origin.y()-margin-labelBounds.height(), axisRect.width(), labelBounds.height(), Qt::TextDontClip | Qt::AlignCenter, label);
6238 else if (type == QCPAxis::atBottom)
6238 else if (type == QCPAxis::atBottom)
6239 painter->drawText(origin.x(), origin.y()+margin, axisRect.width(), labelBounds.height(), Qt::TextDontClip | Qt::AlignCenter, label);
6239 painter->drawText(origin.x(), origin.y()+margin, axisRect.width(), labelBounds.height(), Qt::TextDontClip | Qt::AlignCenter, label);
6240 }
6240 }
6241
6241
6242 // set selection boxes:
6242 // set selection boxes:
6243 int selectionTolerance = 0;
6243 int selectionTolerance = 0;
6244 if (mParentPlot)
6244 if (mParentPlot)
6245 selectionTolerance = mParentPlot->selectionTolerance();
6245 selectionTolerance = mParentPlot->selectionTolerance();
6246 else
6246 else
6247 qDebug() << Q_FUNC_INFO << "mParentPlot is null";
6247 qDebug() << Q_FUNC_INFO << "mParentPlot is null";
6248 int selAxisOutSize = qMax(qMax(tickLengthOut, subTickLengthOut), selectionTolerance);
6248 int selAxisOutSize = qMax(qMax(tickLengthOut, subTickLengthOut), selectionTolerance);
6249 int selAxisInSize = selectionTolerance;
6249 int selAxisInSize = selectionTolerance;
6250 int selTickLabelSize;
6250 int selTickLabelSize;
6251 int selTickLabelOffset;
6251 int selTickLabelOffset;
6252 if (tickLabelSide == QCPAxis::lsOutside)
6252 if (tickLabelSide == QCPAxis::lsOutside)
6253 {
6253 {
6254 selTickLabelSize = (QCPAxis::orientation(type) == Qt::Horizontal ? tickLabelsSize.height() : tickLabelsSize.width());
6254 selTickLabelSize = (QCPAxis::orientation(type) == Qt::Horizontal ? tickLabelsSize.height() : tickLabelsSize.width());
6255 selTickLabelOffset = qMax(tickLengthOut, subTickLengthOut)+tickLabelPadding;
6255 selTickLabelOffset = qMax(tickLengthOut, subTickLengthOut)+tickLabelPadding;
6256 } else
6256 } else
6257 {
6257 {
6258 selTickLabelSize = -(QCPAxis::orientation(type) == Qt::Horizontal ? tickLabelsSize.height() : tickLabelsSize.width());
6258 selTickLabelSize = -(QCPAxis::orientation(type) == Qt::Horizontal ? tickLabelsSize.height() : tickLabelsSize.width());
6259 selTickLabelOffset = -(qMax(tickLengthIn, subTickLengthIn)+tickLabelPadding);
6259 selTickLabelOffset = -(qMax(tickLengthIn, subTickLengthIn)+tickLabelPadding);
6260 }
6260 }
6261 int selLabelSize = labelBounds.height();
6261 int selLabelSize = labelBounds.height();
6262 int selLabelOffset = qMax(tickLengthOut, subTickLengthOut)+(!tickLabels.isEmpty() && tickLabelSide == QCPAxis::lsOutside ? tickLabelPadding+selTickLabelSize : 0)+labelPadding;
6262 int selLabelOffset = qMax(tickLengthOut, subTickLengthOut)+(!tickLabels.isEmpty() && tickLabelSide == QCPAxis::lsOutside ? tickLabelPadding+selTickLabelSize : 0)+labelPadding;
6263 if (type == QCPAxis::atLeft)
6263 if (type == QCPAxis::atLeft)
6264 {
6264 {
6265 mAxisSelectionBox.setCoords(origin.x()-selAxisOutSize, axisRect.top(), origin.x()+selAxisInSize, axisRect.bottom());
6265 mAxisSelectionBox.setCoords(origin.x()-selAxisOutSize, axisRect.top(), origin.x()+selAxisInSize, axisRect.bottom());
6266 mTickLabelsSelectionBox.setCoords(origin.x()-selTickLabelOffset-selTickLabelSize, axisRect.top(), origin.x()-selTickLabelOffset, axisRect.bottom());
6266 mTickLabelsSelectionBox.setCoords(origin.x()-selTickLabelOffset-selTickLabelSize, axisRect.top(), origin.x()-selTickLabelOffset, axisRect.bottom());
6267 mLabelSelectionBox.setCoords(origin.x()-selLabelOffset-selLabelSize, axisRect.top(), origin.x()-selLabelOffset, axisRect.bottom());
6267 mLabelSelectionBox.setCoords(origin.x()-selLabelOffset-selLabelSize, axisRect.top(), origin.x()-selLabelOffset, axisRect.bottom());
6268 } else if (type == QCPAxis::atRight)
6268 } else if (type == QCPAxis::atRight)
6269 {
6269 {
6270 mAxisSelectionBox.setCoords(origin.x()-selAxisInSize, axisRect.top(), origin.x()+selAxisOutSize, axisRect.bottom());
6270 mAxisSelectionBox.setCoords(origin.x()-selAxisInSize, axisRect.top(), origin.x()+selAxisOutSize, axisRect.bottom());
6271 mTickLabelsSelectionBox.setCoords(origin.x()+selTickLabelOffset+selTickLabelSize, axisRect.top(), origin.x()+selTickLabelOffset, axisRect.bottom());
6271 mTickLabelsSelectionBox.setCoords(origin.x()+selTickLabelOffset+selTickLabelSize, axisRect.top(), origin.x()+selTickLabelOffset, axisRect.bottom());
6272 mLabelSelectionBox.setCoords(origin.x()+selLabelOffset+selLabelSize, axisRect.top(), origin.x()+selLabelOffset, axisRect.bottom());
6272 mLabelSelectionBox.setCoords(origin.x()+selLabelOffset+selLabelSize, axisRect.top(), origin.x()+selLabelOffset, axisRect.bottom());
6273 } else if (type == QCPAxis::atTop)
6273 } else if (type == QCPAxis::atTop)
6274 {
6274 {
6275 mAxisSelectionBox.setCoords(axisRect.left(), origin.y()-selAxisOutSize, axisRect.right(), origin.y()+selAxisInSize);
6275 mAxisSelectionBox.setCoords(axisRect.left(), origin.y()-selAxisOutSize, axisRect.right(), origin.y()+selAxisInSize);
6276 mTickLabelsSelectionBox.setCoords(axisRect.left(), origin.y()-selTickLabelOffset-selTickLabelSize, axisRect.right(), origin.y()-selTickLabelOffset);
6276 mTickLabelsSelectionBox.setCoords(axisRect.left(), origin.y()-selTickLabelOffset-selTickLabelSize, axisRect.right(), origin.y()-selTickLabelOffset);
6277 mLabelSelectionBox.setCoords(axisRect.left(), origin.y()-selLabelOffset-selLabelSize, axisRect.right(), origin.y()-selLabelOffset);
6277 mLabelSelectionBox.setCoords(axisRect.left(), origin.y()-selLabelOffset-selLabelSize, axisRect.right(), origin.y()-selLabelOffset);
6278 } else if (type == QCPAxis::atBottom)
6278 } else if (type == QCPAxis::atBottom)
6279 {
6279 {
6280 mAxisSelectionBox.setCoords(axisRect.left(), origin.y()-selAxisInSize, axisRect.right(), origin.y()+selAxisOutSize);
6280 mAxisSelectionBox.setCoords(axisRect.left(), origin.y()-selAxisInSize, axisRect.right(), origin.y()+selAxisOutSize);
6281 mTickLabelsSelectionBox.setCoords(axisRect.left(), origin.y()+selTickLabelOffset+selTickLabelSize, axisRect.right(), origin.y()+selTickLabelOffset);
6281 mTickLabelsSelectionBox.setCoords(axisRect.left(), origin.y()+selTickLabelOffset+selTickLabelSize, axisRect.right(), origin.y()+selTickLabelOffset);
6282 mLabelSelectionBox.setCoords(axisRect.left(), origin.y()+selLabelOffset+selLabelSize, axisRect.right(), origin.y()+selLabelOffset);
6282 mLabelSelectionBox.setCoords(axisRect.left(), origin.y()+selLabelOffset+selLabelSize, axisRect.right(), origin.y()+selLabelOffset);
6283 }
6283 }
6284 mAxisSelectionBox = mAxisSelectionBox.normalized();
6284 mAxisSelectionBox = mAxisSelectionBox.normalized();
6285 mTickLabelsSelectionBox = mTickLabelsSelectionBox.normalized();
6285 mTickLabelsSelectionBox = mTickLabelsSelectionBox.normalized();
6286 mLabelSelectionBox = mLabelSelectionBox.normalized();
6286 mLabelSelectionBox = mLabelSelectionBox.normalized();
6287 // draw hitboxes for debug purposes:
6287 // draw hitboxes for debug purposes:
6288 //painter->setBrush(Qt::NoBrush);
6288 //painter->setBrush(Qt::NoBrush);
6289 //painter->drawRects(QVector<QRect>() << mAxisSelectionBox << mTickLabelsSelectionBox << mLabelSelectionBox);
6289 //painter->drawRects(QVector<QRect>() << mAxisSelectionBox << mTickLabelsSelectionBox << mLabelSelectionBox);
6290 }
6290 }
6291
6291
6292 /*! \internal
6292 /*! \internal
@@ -6296,35 +6296,35 void QCPAxisPainterPrivate::draw(QCPPain
6296 */
6296 */
6297 int QCPAxisPainterPrivate::size() const
6297 int QCPAxisPainterPrivate::size() const
6298 {
6298 {
6299 int result = 0;
6299 int result = 0;
6300
6300
6301 // get length of tick marks pointing outwards:
6301 // get length of tick marks pointing outwards:
6302 if (!tickPositions.isEmpty())
6302 if (!tickPositions.isEmpty())
6303 result += qMax(0, qMax(tickLengthOut, subTickLengthOut));
6303 result += qMax(0, qMax(tickLengthOut, subTickLengthOut));
6304
6304
6305 // calculate size of tick labels:
6305 // calculate size of tick labels:
6306 if (tickLabelSide == QCPAxis::lsOutside)
6306 if (tickLabelSide == QCPAxis::lsOutside)
6307 {
6307 {
6308 QSize tickLabelsSize(0, 0);
6308 QSize tickLabelsSize(0, 0);
6309 if (!tickLabels.isEmpty())
6309 if (!tickLabels.isEmpty())
6310 {
6310 {
6311 for (int i=0; i<tickLabels.size(); ++i)
6311 for (int i=0; i<tickLabels.size(); ++i)
6312 getMaxTickLabelSize(tickLabelFont, tickLabels.at(i), &tickLabelsSize);
6312 getMaxTickLabelSize(tickLabelFont, tickLabels.at(i), &tickLabelsSize);
6313 result += QCPAxis::orientation(type) == Qt::Horizontal ? tickLabelsSize.height() : tickLabelsSize.width();
6313 result += QCPAxis::orientation(type) == Qt::Horizontal ? tickLabelsSize.height() : tickLabelsSize.width();
6314 result += tickLabelPadding;
6314 result += tickLabelPadding;
6315 }
6315 }
6316 }
6316 }
6317
6317
6318 // calculate size of axis label (only height needed, because left/right labels are rotated by 90 degrees):
6318 // calculate size of axis label (only height needed, because left/right labels are rotated by 90 degrees):
6319 if (!label.isEmpty())
6319 if (!label.isEmpty())
6320 {
6320 {
6321 QFontMetrics fontMetrics(labelFont);
6321 QFontMetrics fontMetrics(labelFont);
6322 QRect bounds;
6322 QRect bounds;
6323 bounds = fontMetrics.boundingRect(0, 0, 0, 0, Qt::TextDontClip | Qt::AlignHCenter | Qt::AlignVCenter, label);
6323 bounds = fontMetrics.boundingRect(0, 0, 0, 0, Qt::TextDontClip | Qt::AlignHCenter | Qt::AlignVCenter, label);
6324 result += bounds.height() + labelPadding;
6324 result += bounds.height() + labelPadding;
6325 }
6325 }
6326
6326
6327 return result;
6327 return result;
6328 }
6328 }
6329
6329
6330 /*! \internal
6330 /*! \internal
@@ -6335,7 +6335,7 int QCPAxisPainterPrivate::size() const
6335 */
6335 */
6336 void QCPAxisPainterPrivate::clearCache()
6336 void QCPAxisPainterPrivate::clearCache()
6337 {
6337 {
6338 mLabelCache.clear();
6338 mLabelCache.clear();
6339 }
6339 }
6340
6340
6341 /*! \internal
6341 /*! \internal
@@ -6347,14 +6347,14 void QCPAxisPainterPrivate::clearCache()
6347 */
6347 */
6348 QByteArray QCPAxisPainterPrivate::generateLabelParameterHash() const
6348 QByteArray QCPAxisPainterPrivate::generateLabelParameterHash() const
6349 {
6349 {
6350 QByteArray result;
6350 QByteArray result;
6351 result.append(QByteArray::number(tickLabelRotation));
6351 result.append(QByteArray::number(tickLabelRotation));
6352 result.append(QByteArray::number((int)tickLabelSide));
6352 result.append(QByteArray::number((int)tickLabelSide));
6353 result.append(QByteArray::number((int)substituteExponent));
6353 result.append(QByteArray::number((int)substituteExponent));
6354 result.append(QByteArray::number((int)numberMultiplyCross));
6354 result.append(QByteArray::number((int)numberMultiplyCross));
6355 result.append(tickLabelColor.name().toLatin1()+QByteArray::number(tickLabelColor.alpha(), 16));
6355 result.append(tickLabelColor.name().toLatin1()+QByteArray::number(tickLabelColor.alpha(), 16));
6356 result.append(tickLabelFont.toString().toLatin1());
6356 result.append(tickLabelFont.toString().toLatin1());
6357 return result;
6357 return result;
6358 }
6358 }
6359
6359
6360 /*! \internal
6360 /*! \internal
@@ -6378,78 +6378,78 QByteArray QCPAxisPainterPrivate::genera
6378 */
6378 */
6379 void QCPAxisPainterPrivate::placeTickLabel(QCPPainter *painter, double position, int distanceToAxis, const QString &text, QSize *tickLabelsSize)
6379 void QCPAxisPainterPrivate::placeTickLabel(QCPPainter *painter, double position, int distanceToAxis, const QString &text, QSize *tickLabelsSize)
6380 {
6380 {
6381 // warning: if you change anything here, also adapt getMaxTickLabelSize() accordingly!
6381 // warning: if you change anything here, also adapt getMaxTickLabelSize() accordingly!
6382 if (text.isEmpty()) return;
6382 if (text.isEmpty()) return;
6383 QSize finalSize;
6383 QSize finalSize;
6384 QPointF labelAnchor;
6384 QPointF labelAnchor;
6385 switch (type)
6385 switch (type)
6386 {
6386 {
6387 case QCPAxis::atLeft: labelAnchor = QPointF(axisRect.left()-distanceToAxis-offset, position); break;
6387 case QCPAxis::atLeft: labelAnchor = QPointF(axisRect.left()-distanceToAxis-offset, position); break;
6388 case QCPAxis::atRight: labelAnchor = QPointF(axisRect.right()+distanceToAxis+offset, position); break;
6388 case QCPAxis::atRight: labelAnchor = QPointF(axisRect.right()+distanceToAxis+offset, position); break;
6389 case QCPAxis::atTop: labelAnchor = QPointF(position, axisRect.top()-distanceToAxis-offset); break;
6389 case QCPAxis::atTop: labelAnchor = QPointF(position, axisRect.top()-distanceToAxis-offset); break;
6390 case QCPAxis::atBottom: labelAnchor = QPointF(position, axisRect.bottom()+distanceToAxis+offset); break;
6390 case QCPAxis::atBottom: labelAnchor = QPointF(position, axisRect.bottom()+distanceToAxis+offset); break;
6391 }
6391 }
6392 if (mParentPlot->plottingHints().testFlag(QCP::phCacheLabels) && !painter->modes().testFlag(QCPPainter::pmNoCaching)) // label caching enabled
6392 if (mParentPlot->plottingHints().testFlag(QCP::phCacheLabels) && !painter->modes().testFlag(QCPPainter::pmNoCaching)) // label caching enabled
6393 {
6393 {
6394 if (!mLabelCache.contains(text)) // no cached label exists, create it
6394 if (!mLabelCache.contains(text)) // no cached label exists, create it
6395 {
6395 {
6396 CachedLabel *newCachedLabel = new CachedLabel;
6396 CachedLabel *newCachedLabel = new CachedLabel;
6397 TickLabelData labelData = getTickLabelData(painter->font(), text);
6397 TickLabelData labelData = getTickLabelData(painter->font(), text);
6398 newCachedLabel->offset = getTickLabelDrawOffset(labelData)+labelData.rotatedTotalBounds.topLeft();
6398 newCachedLabel->offset = getTickLabelDrawOffset(labelData)+labelData.rotatedTotalBounds.topLeft();
6399 newCachedLabel->pixmap = QPixmap(labelData.rotatedTotalBounds.size());
6399 newCachedLabel->pixmap = QPixmap(labelData.rotatedTotalBounds.size());
6400 newCachedLabel->pixmap.fill(Qt::transparent);
6400 newCachedLabel->pixmap.fill(Qt::transparent);
6401 QCPPainter cachePainter(&newCachedLabel->pixmap);
6401 QCPPainter cachePainter(&newCachedLabel->pixmap);
6402 cachePainter.setPen(painter->pen());
6402 cachePainter.setPen(painter->pen());
6403 drawTickLabel(&cachePainter, -labelData.rotatedTotalBounds.topLeft().x(), -labelData.rotatedTotalBounds.topLeft().y(), labelData);
6403 drawTickLabel(&cachePainter, -labelData.rotatedTotalBounds.topLeft().x(), -labelData.rotatedTotalBounds.topLeft().y(), labelData);
6404 mLabelCache.insert(text, newCachedLabel, 1);
6404 mLabelCache.insert(text, newCachedLabel, 1);
6405 }
6405 }
6406 // draw cached label:
6406 // draw cached label:
6407 const CachedLabel *cachedLabel = mLabelCache.object(text);
6407 const CachedLabel *cachedLabel = mLabelCache.object(text);
6408 // if label would be partly clipped by widget border on sides, don't draw it (only for outside tick labels):
6408 // if label would be partly clipped by widget border on sides, don't draw it (only for outside tick labels):
6409 if (tickLabelSide == QCPAxis::lsOutside)
6409 if (tickLabelSide == QCPAxis::lsOutside)
6410 {
6410 {
6411 if (QCPAxis::orientation(type) == Qt::Horizontal)
6411 if (QCPAxis::orientation(type) == Qt::Horizontal)
6412 {
6412 {
6413 if (labelAnchor.x()+cachedLabel->offset.x()+cachedLabel->pixmap.width() > viewportRect.right() ||
6413 if (labelAnchor.x()+cachedLabel->offset.x()+cachedLabel->pixmap.width() > viewportRect.right() ||
6414 labelAnchor.x()+cachedLabel->offset.x() < viewportRect.left())
6414 labelAnchor.x()+cachedLabel->offset.x() < viewportRect.left())
6415 return;
6415 return;
6416 } else
6416 } else
6417 {
6417 {
6418 if (labelAnchor.y()+cachedLabel->offset.y()+cachedLabel->pixmap.height() >viewportRect.bottom() ||
6418 if (labelAnchor.y()+cachedLabel->offset.y()+cachedLabel->pixmap.height() >viewportRect.bottom() ||
6419 labelAnchor.y()+cachedLabel->offset.y() < viewportRect.top())
6419 labelAnchor.y()+cachedLabel->offset.y() < viewportRect.top())
6420 return;
6420 return;
6421 }
6421 }
6422 }
6422 }
6423 painter->drawPixmap(labelAnchor+cachedLabel->offset, cachedLabel->pixmap);
6423 painter->drawPixmap(labelAnchor+cachedLabel->offset, cachedLabel->pixmap);
6424 finalSize = cachedLabel->pixmap.size();
6424 finalSize = cachedLabel->pixmap.size();
6425 } else // label caching disabled, draw text directly on surface:
6425 } else // label caching disabled, draw text directly on surface:
6426 {
6426 {
6427 TickLabelData labelData = getTickLabelData(painter->font(), text);
6427 TickLabelData labelData = getTickLabelData(painter->font(), text);
6428 QPointF finalPosition = labelAnchor + getTickLabelDrawOffset(labelData);
6428 QPointF finalPosition = labelAnchor + getTickLabelDrawOffset(labelData);
6429 // if label would be partly clipped by widget border on sides, don't draw it (only for outside tick labels):
6429 // if label would be partly clipped by widget border on sides, don't draw it (only for outside tick labels):
6430 if (tickLabelSide == QCPAxis::lsOutside)
6430 if (tickLabelSide == QCPAxis::lsOutside)
6431 {
6431 {
6432 if (QCPAxis::orientation(type) == Qt::Horizontal)
6432 if (QCPAxis::orientation(type) == Qt::Horizontal)
6433 {
6433 {
6434 if (finalPosition.x()+(labelData.rotatedTotalBounds.width()+labelData.rotatedTotalBounds.left()) > viewportRect.right() ||
6434 if (finalPosition.x()+(labelData.rotatedTotalBounds.width()+labelData.rotatedTotalBounds.left()) > viewportRect.right() ||
6435 finalPosition.x()+labelData.rotatedTotalBounds.left() < viewportRect.left())
6435 finalPosition.x()+labelData.rotatedTotalBounds.left() < viewportRect.left())
6436 return;
6436 return;
6437 } else
6437 } else
6438 {
6438 {
6439 if (finalPosition.y()+(labelData.rotatedTotalBounds.height()+labelData.rotatedTotalBounds.top()) > viewportRect.bottom() ||
6439 if (finalPosition.y()+(labelData.rotatedTotalBounds.height()+labelData.rotatedTotalBounds.top()) > viewportRect.bottom() ||
6440 finalPosition.y()+labelData.rotatedTotalBounds.top() < viewportRect.top())
6440 finalPosition.y()+labelData.rotatedTotalBounds.top() < viewportRect.top())
6441 return;
6441 return;
6442 }
6442 }
6443 }
6443 }
6444 drawTickLabel(painter, finalPosition.x(), finalPosition.y(), labelData);
6444 drawTickLabel(painter, finalPosition.x(), finalPosition.y(), labelData);
6445 finalSize = labelData.rotatedTotalBounds.size();
6445 finalSize = labelData.rotatedTotalBounds.size();
6446 }
6446 }
6447
6447
6448 // expand passed tickLabelsSize if current tick label is larger:
6448 // expand passed tickLabelsSize if current tick label is larger:
6449 if (finalSize.width() > tickLabelsSize->width())
6449 if (finalSize.width() > tickLabelsSize->width())
6450 tickLabelsSize->setWidth(finalSize.width());
6450 tickLabelsSize->setWidth(finalSize.width());
6451 if (finalSize.height() > tickLabelsSize->height())
6451 if (finalSize.height() > tickLabelsSize->height())
6452 tickLabelsSize->setHeight(finalSize.height());
6452 tickLabelsSize->setHeight(finalSize.height());
6453 }
6453 }
6454
6454
6455 /*! \internal
6455 /*! \internal
@@ -6463,31 +6463,31 void QCPAxisPainterPrivate::placeTickLab
6463 */
6463 */
6464 void QCPAxisPainterPrivate::drawTickLabel(QCPPainter *painter, double x, double y, const TickLabelData &labelData) const
6464 void QCPAxisPainterPrivate::drawTickLabel(QCPPainter *painter, double x, double y, const TickLabelData &labelData) const
6465 {
6465 {
6466 // backup painter settings that we're about to change:
6466 // backup painter settings that we're about to change:
6467 QTransform oldTransform = painter->transform();
6467 QTransform oldTransform = painter->transform();
6468 QFont oldFont = painter->font();
6468 QFont oldFont = painter->font();
6469
6469
6470 // transform painter to position/rotation:
6470 // transform painter to position/rotation:
6471 painter->translate(x, y);
6471 painter->translate(x, y);
6472 if (!qFuzzyIsNull(tickLabelRotation))
6472 if (!qFuzzyIsNull(tickLabelRotation))
6473 painter->rotate(tickLabelRotation);
6473 painter->rotate(tickLabelRotation);
6474
6474
6475 // draw text:
6475 // draw text:
6476 if (!labelData.expPart.isEmpty()) // indicator that beautiful powers must be used
6476 if (!labelData.expPart.isEmpty()) // indicator that beautiful powers must be used
6477 {
6477 {
6478 painter->setFont(labelData.baseFont);
6478 painter->setFont(labelData.baseFont);
6479 painter->drawText(0, 0, 0, 0, Qt::TextDontClip, labelData.basePart);
6479 painter->drawText(0, 0, 0, 0, Qt::TextDontClip, labelData.basePart);
6480 painter->setFont(labelData.expFont);
6480 painter->setFont(labelData.expFont);
6481 painter->drawText(labelData.baseBounds.width()+1, 0, labelData.expBounds.width(), labelData.expBounds.height(), Qt::TextDontClip, labelData.expPart);
6481 painter->drawText(labelData.baseBounds.width()+1, 0, labelData.expBounds.width(), labelData.expBounds.height(), Qt::TextDontClip, labelData.expPart);
6482 } else
6482 } else
6483 {
6483 {
6484 painter->setFont(labelData.baseFont);
6484 painter->setFont(labelData.baseFont);
6485 painter->drawText(0, 0, labelData.totalBounds.width(), labelData.totalBounds.height(), Qt::TextDontClip | Qt::AlignHCenter, labelData.basePart);
6485 painter->drawText(0, 0, labelData.totalBounds.width(), labelData.totalBounds.height(), Qt::TextDontClip | Qt::AlignHCenter, labelData.basePart);
6486 }
6486 }
6487
6487
6488 // reset painter settings to what it was before:
6488 // reset painter settings to what it was before:
6489 painter->setTransform(oldTransform);
6489 painter->setTransform(oldTransform);
6490 painter->setFont(oldFont);
6490 painter->setFont(oldFont);
6491 }
6491 }
6492
6492
6493 /*! \internal
6493 /*! \internal
@@ -6500,61 +6500,61 void QCPAxisPainterPrivate::drawTickLabe
6500 */
6500 */
6501 QCPAxisPainterPrivate::TickLabelData QCPAxisPainterPrivate::getTickLabelData(const QFont &font, const QString &text) const
6501 QCPAxisPainterPrivate::TickLabelData QCPAxisPainterPrivate::getTickLabelData(const QFont &font, const QString &text) const
6502 {
6502 {
6503 TickLabelData result;
6503 TickLabelData result;
6504
6504
6505 // determine whether beautiful decimal powers should be used
6505 // determine whether beautiful decimal powers should be used
6506 bool useBeautifulPowers = false;
6506 bool useBeautifulPowers = false;
6507 int ePos = -1;
6507 int ePos = -1;
6508 if (substituteExponent)
6508 if (substituteExponent)
6509 {
6509 {
6510 ePos = text.indexOf(QLatin1Char('e'));
6510 ePos = text.indexOf(QLatin1Char('e'));
6511 if (ePos > -1)
6511 if (ePos > -1)
6512 useBeautifulPowers = true;
6512 useBeautifulPowers = true;
6513 }
6513 }
6514
6514
6515 // calculate text bounding rects and do string preparation for beautiful decimal powers:
6515 // calculate text bounding rects and do string preparation for beautiful decimal powers:
6516 result.baseFont = font;
6516 result.baseFont = font;
6517 if (result.baseFont.pointSizeF() > 0) // On some rare systems, this sometimes is initialized with -1 (Qt bug?), so we check here before possibly setting a negative value in the next line
6517 if (result.baseFont.pointSizeF() > 0) // On some rare systems, this sometimes is initialized with -1 (Qt bug?), so we check here before possibly setting a negative value in the next line
6518 result.baseFont.setPointSizeF(result.baseFont.pointSizeF()+0.05); // QFontMetrics.boundingRect has a bug for exact point sizes that make the results oscillate due to internal rounding
6518 result.baseFont.setPointSizeF(result.baseFont.pointSizeF()+0.05); // QFontMetrics.boundingRect has a bug for exact point sizes that make the results oscillate due to internal rounding
6519 if (useBeautifulPowers)
6519 if (useBeautifulPowers)
6520 {
6520 {
6521 // split text into parts of number/symbol that will be drawn normally and part that will be drawn as exponent:
6521 // split text into parts of number/symbol that will be drawn normally and part that will be drawn as exponent:
6522 result.basePart = text.left(ePos);
6522 result.basePart = text.left(ePos);
6523 // in log scaling, we want to turn "1*10^n" into "10^n", else add multiplication sign and decimal base:
6523 // in log scaling, we want to turn "1*10^n" into "10^n", else add multiplication sign and decimal base:
6524 if (abbreviateDecimalPowers && result.basePart == QLatin1String("1"))
6524 if (abbreviateDecimalPowers && result.basePart == QLatin1String("1"))
6525 result.basePart = QLatin1String("10");
6525 result.basePart = QLatin1String("10");
6526 else
6526 else
6527 result.basePart += (numberMultiplyCross ? QString(QChar(215)) : QString(QChar(183))) + QLatin1String("10");
6527 result.basePart += (numberMultiplyCross ? QString(QChar(215)) : QString(QChar(183))) + QLatin1String("10");
6528 result.expPart = text.mid(ePos+1);
6528 result.expPart = text.mid(ePos+1);
6529 // clip "+" and leading zeros off expPart:
6529 // clip "+" and leading zeros off expPart:
6530 while (result.expPart.length() > 2 && result.expPart.at(1) == QLatin1Char('0')) // length > 2 so we leave one zero when numberFormatChar is 'e'
6530 while (result.expPart.length() > 2 && result.expPart.at(1) == QLatin1Char('0')) // length > 2 so we leave one zero when numberFormatChar is 'e'
6531 result.expPart.remove(1, 1);
6531 result.expPart.remove(1, 1);
6532 if (!result.expPart.isEmpty() && result.expPart.at(0) == QLatin1Char('+'))
6532 if (!result.expPart.isEmpty() && result.expPart.at(0) == QLatin1Char('+'))
6533 result.expPart.remove(0, 1);
6533 result.expPart.remove(0, 1);
6534 // prepare smaller font for exponent:
6534 // prepare smaller font for exponent:
6535 result.expFont = font;
6535 result.expFont = font;
6536 result.expFont.setPointSize(result.expFont.pointSize()*0.75);
6536 result.expFont.setPointSize(result.expFont.pointSize()*0.75);
6537 // calculate bounding rects of base part, exponent part and total one:
6537 // calculate bounding rects of base part, exponent part and total one:
6538 result.baseBounds = QFontMetrics(result.baseFont).boundingRect(0, 0, 0, 0, Qt::TextDontClip, result.basePart);
6538 result.baseBounds = QFontMetrics(result.baseFont).boundingRect(0, 0, 0, 0, Qt::TextDontClip, result.basePart);
6539 result.expBounds = QFontMetrics(result.expFont).boundingRect(0, 0, 0, 0, Qt::TextDontClip, result.expPart);
6539 result.expBounds = QFontMetrics(result.expFont).boundingRect(0, 0, 0, 0, Qt::TextDontClip, result.expPart);
6540 result.totalBounds = result.baseBounds.adjusted(0, 0, result.expBounds.width()+2, 0); // +2 consists of the 1 pixel spacing between base and exponent (see drawTickLabel) and an extra pixel to include AA
6540 result.totalBounds = result.baseBounds.adjusted(0, 0, result.expBounds.width()+2, 0); // +2 consists of the 1 pixel spacing between base and exponent (see drawTickLabel) and an extra pixel to include AA
6541 } else // useBeautifulPowers == false
6541 } else // useBeautifulPowers == false
6542 {
6542 {
6543 result.basePart = text;
6543 result.basePart = text;
6544 result.totalBounds = QFontMetrics(result.baseFont).boundingRect(0, 0, 0, 0, Qt::TextDontClip | Qt::AlignHCenter, result.basePart);
6544 result.totalBounds = QFontMetrics(result.baseFont).boundingRect(0, 0, 0, 0, Qt::TextDontClip | Qt::AlignHCenter, result.basePart);
6545 }
6545 }
6546 result.totalBounds.moveTopLeft(QPoint(0, 0)); // want bounding box aligned top left at origin, independent of how it was created, to make further processing simpler
6546 result.totalBounds.moveTopLeft(QPoint(0, 0)); // want bounding box aligned top left at origin, independent of how it was created, to make further processing simpler
6547
6547
6548 // calculate possibly different bounding rect after rotation:
6548 // calculate possibly different bounding rect after rotation:
6549 result.rotatedTotalBounds = result.totalBounds;
6549 result.rotatedTotalBounds = result.totalBounds;
6550 if (!qFuzzyIsNull(tickLabelRotation))
6550 if (!qFuzzyIsNull(tickLabelRotation))
6551 {
6551 {
6552 QTransform transform;
6552 QTransform transform;
6553 transform.rotate(tickLabelRotation);
6553 transform.rotate(tickLabelRotation);
6554 result.rotatedTotalBounds = transform.mapRect(result.rotatedTotalBounds);
6554 result.rotatedTotalBounds = transform.mapRect(result.rotatedTotalBounds);
6555 }
6555 }
6556
6556
6557 return result;
6557 return result;
6558 }
6558 }
6559
6559
6560 /*! \internal
6560 /*! \internal
@@ -6569,7 +6569,7 QCPAxisPainterPrivate::TickLabelData QCP
6569 */
6569 */
6570 QPointF QCPAxisPainterPrivate::getTickLabelDrawOffset(const TickLabelData &labelData) const
6570 QPointF QCPAxisPainterPrivate::getTickLabelDrawOffset(const TickLabelData &labelData) const
6571 {
6571 {
6572 /*
6572 /*
6573 calculate label offset from base point at tick (non-trivial, for best visual appearance): short
6573 calculate label offset from base point at tick (non-trivial, for best visual appearance): short
6574 explanation for bottom axis: The anchor, i.e. the point in the label that is placed
6574 explanation for bottom axis: The anchor, i.e. the point in the label that is placed
6575 horizontally under the corresponding tick is always on the label side that is closer to the
6575 horizontally under the corresponding tick is always on the label side that is closer to the
@@ -6579,85 +6579,85 QPointF QCPAxisPainterPrivate::getTickLa
6579 time, a 45 degree rotated text will "point toward" its tick, as is typical for rotated tick
6579 time, a 45 degree rotated text will "point toward" its tick, as is typical for rotated tick
6580 labels.
6580 labels.
6581 */
6581 */
6582 bool doRotation = !qFuzzyIsNull(tickLabelRotation);
6582 bool doRotation = !qFuzzyIsNull(tickLabelRotation);
6583 bool flip = qFuzzyCompare(qAbs(tickLabelRotation), 90.0); // perfect +/-90 degree flip. Indicates vertical label centering on vertical axes.
6583 bool flip = qFuzzyCompare(qAbs(tickLabelRotation), 90.0); // perfect +/-90 degree flip. Indicates vertical label centering on vertical axes.
6584 double radians = tickLabelRotation/180.0*M_PI;
6584 double radians = tickLabelRotation/180.0*M_PI;
6585 int x=0, y=0;
6585 int x=0, y=0;
6586 if ((type == QCPAxis::atLeft && tickLabelSide == QCPAxis::lsOutside) || (type == QCPAxis::atRight && tickLabelSide == QCPAxis::lsInside)) // Anchor at right side of tick label
6586 if ((type == QCPAxis::atLeft && tickLabelSide == QCPAxis::lsOutside) || (type == QCPAxis::atRight && tickLabelSide == QCPAxis::lsInside)) // Anchor at right side of tick label
6587 {
6587 {
6588 if (doRotation)
6588 if (doRotation)
6589 {
6589 {
6590 if (tickLabelRotation > 0)
6590 if (tickLabelRotation > 0)
6591 {
6591 {
6592 x = -qCos(radians)*labelData.totalBounds.width();
6592 x = -qCos(radians)*labelData.totalBounds.width();
6593 y = flip ? -labelData.totalBounds.width()/2.0 : -qSin(radians)*labelData.totalBounds.width()-qCos(radians)*labelData.totalBounds.height()/2.0;
6593 y = flip ? -labelData.totalBounds.width()/2.0 : -qSin(radians)*labelData.totalBounds.width()-qCos(radians)*labelData.totalBounds.height()/2.0;
6594 } else
6594 } else
6595 {
6595 {
6596 x = -qCos(-radians)*labelData.totalBounds.width()-qSin(-radians)*labelData.totalBounds.height();
6596 x = -qCos(-radians)*labelData.totalBounds.width()-qSin(-radians)*labelData.totalBounds.height();
6597 y = flip ? +labelData.totalBounds.width()/2.0 : +qSin(-radians)*labelData.totalBounds.width()-qCos(-radians)*labelData.totalBounds.height()/2.0;
6597 y = flip ? +labelData.totalBounds.width()/2.0 : +qSin(-radians)*labelData.totalBounds.width()-qCos(-radians)*labelData.totalBounds.height()/2.0;
6598 }
6598 }
6599 } else
6599 } else
6600 {
6600 {
6601 x = -labelData.totalBounds.width();
6601 x = -labelData.totalBounds.width();
6602 y = -labelData.totalBounds.height()/2.0;
6602 y = -labelData.totalBounds.height()/2.0;
6603 }
6603 }
6604 } else if ((type == QCPAxis::atRight && tickLabelSide == QCPAxis::lsOutside) || (type == QCPAxis::atLeft && tickLabelSide == QCPAxis::lsInside)) // Anchor at left side of tick label
6604 } else if ((type == QCPAxis::atRight && tickLabelSide == QCPAxis::lsOutside) || (type == QCPAxis::atLeft && tickLabelSide == QCPAxis::lsInside)) // Anchor at left side of tick label
6605 {
6605 {
6606 if (doRotation)
6606 if (doRotation)
6607 {
6607 {
6608 if (tickLabelRotation > 0)
6608 if (tickLabelRotation > 0)
6609 {
6609 {
6610 x = +qSin(radians)*labelData.totalBounds.height();
6610 x = +qSin(radians)*labelData.totalBounds.height();
6611 y = flip ? -labelData.totalBounds.width()/2.0 : -qCos(radians)*labelData.totalBounds.height()/2.0;
6611 y = flip ? -labelData.totalBounds.width()/2.0 : -qCos(radians)*labelData.totalBounds.height()/2.0;
6612 } else
6612 } else
6613 {
6613 {
6614 x = 0;
6614 x = 0;
6615 y = flip ? +labelData.totalBounds.width()/2.0 : -qCos(-radians)*labelData.totalBounds.height()/2.0;
6615 y = flip ? +labelData.totalBounds.width()/2.0 : -qCos(-radians)*labelData.totalBounds.height()/2.0;
6616 }
6616 }
6617 } else
6617 } else
6618 {
6618 {
6619 x = 0;
6619 x = 0;
6620 y = -labelData.totalBounds.height()/2.0;
6620 y = -labelData.totalBounds.height()/2.0;
6621 }
6621 }
6622 } else if ((type == QCPAxis::atTop && tickLabelSide == QCPAxis::lsOutside) || (type == QCPAxis::atBottom && tickLabelSide == QCPAxis::lsInside)) // Anchor at bottom side of tick label
6622 } else if ((type == QCPAxis::atTop && tickLabelSide == QCPAxis::lsOutside) || (type == QCPAxis::atBottom && tickLabelSide == QCPAxis::lsInside)) // Anchor at bottom side of tick label
6623 {
6623 {
6624 if (doRotation)
6624 if (doRotation)
6625 {
6625 {
6626 if (tickLabelRotation > 0)
6626 if (tickLabelRotation > 0)
6627 {
6627 {
6628 x = -qCos(radians)*labelData.totalBounds.width()+qSin(radians)*labelData.totalBounds.height()/2.0;
6628 x = -qCos(radians)*labelData.totalBounds.width()+qSin(radians)*labelData.totalBounds.height()/2.0;
6629 y = -qSin(radians)*labelData.totalBounds.width()-qCos(radians)*labelData.totalBounds.height();
6629 y = -qSin(radians)*labelData.totalBounds.width()-qCos(radians)*labelData.totalBounds.height();
6630 } else
6630 } else
6631 {
6631 {
6632 x = -qSin(-radians)*labelData.totalBounds.height()/2.0;
6632 x = -qSin(-radians)*labelData.totalBounds.height()/2.0;
6633 y = -qCos(-radians)*labelData.totalBounds.height();
6633 y = -qCos(-radians)*labelData.totalBounds.height();
6634 }
6634 }
6635 } else
6635 } else
6636 {
6636 {
6637 x = -labelData.totalBounds.width()/2.0;
6637 x = -labelData.totalBounds.width()/2.0;
6638 y = -labelData.totalBounds.height();
6638 y = -labelData.totalBounds.height();
6639 }
6639 }
6640 } else if ((type == QCPAxis::atBottom && tickLabelSide == QCPAxis::lsOutside) || (type == QCPAxis::atTop && tickLabelSide == QCPAxis::lsInside)) // Anchor at top side of tick label
6640 } else if ((type == QCPAxis::atBottom && tickLabelSide == QCPAxis::lsOutside) || (type == QCPAxis::atTop && tickLabelSide == QCPAxis::lsInside)) // Anchor at top side of tick label
6641 {
6641 {
6642 if (doRotation)
6642 if (doRotation)
6643 {
6643 {
6644 if (tickLabelRotation > 0)
6644 if (tickLabelRotation > 0)
6645 {
6645 {
6646 x = +qSin(radians)*labelData.totalBounds.height()/2.0;
6646 x = +qSin(radians)*labelData.totalBounds.height()/2.0;
6647 y = 0;
6647 y = 0;
6648 } else
6648 } else
6649 {
6649 {
6650 x = -qCos(-radians)*labelData.totalBounds.width()-qSin(-radians)*labelData.totalBounds.height()/2.0;
6650 x = -qCos(-radians)*labelData.totalBounds.width()-qSin(-radians)*labelData.totalBounds.height()/2.0;
6651 y = +qSin(-radians)*labelData.totalBounds.width();
6651 y = +qSin(-radians)*labelData.totalBounds.width();
6652 }
6652 }
6653 } else
6653 } else
6654 {
6654 {
6655 x = -labelData.totalBounds.width()/2.0;
6655 x = -labelData.totalBounds.width()/2.0;
6656 y = 0;
6656 y = 0;
6657 }
6657 }
6658 }
6658 }
6659
6659
6660 return QPointF(x, y);
6660 return QPointF(x, y);
6661 }
6661 }
6662
6662
6663 /*! \internal
6663 /*! \internal
@@ -6669,23 +6669,23 QPointF QCPAxisPainterPrivate::getTickLa
6669 */
6669 */
6670 void QCPAxisPainterPrivate::getMaxTickLabelSize(const QFont &font, const QString &text, QSize *tickLabelsSize) const
6670 void QCPAxisPainterPrivate::getMaxTickLabelSize(const QFont &font, const QString &text, QSize *tickLabelsSize) const
6671 {
6671 {
6672 // note: this function must return the same tick label sizes as the placeTickLabel function.
6672 // note: this function must return the same tick label sizes as the placeTickLabel function.
6673 QSize finalSize;
6673 QSize finalSize;
6674 if (mParentPlot->plottingHints().testFlag(QCP::phCacheLabels) && mLabelCache.contains(text)) // label caching enabled and have cached label
6674 if (mParentPlot->plottingHints().testFlag(QCP::phCacheLabels) && mLabelCache.contains(text)) // label caching enabled and have cached label
6675 {
6675 {
6676 const CachedLabel *cachedLabel = mLabelCache.object(text);
6676 const CachedLabel *cachedLabel = mLabelCache.object(text);
6677 finalSize = cachedLabel->pixmap.size();
6677 finalSize = cachedLabel->pixmap.size();
6678 } else // label caching disabled or no label with this text cached:
6678 } else // label caching disabled or no label with this text cached:
6679 {
6679 {
6680 TickLabelData labelData = getTickLabelData(font, text);
6680 TickLabelData labelData = getTickLabelData(font, text);
6681 finalSize = labelData.rotatedTotalBounds.size();
6681 finalSize = labelData.rotatedTotalBounds.size();
6682 }
6682 }
6683
6683
6684 // expand passed tickLabelsSize if current tick label is larger:
6684 // expand passed tickLabelsSize if current tick label is larger:
6685 if (finalSize.width() > tickLabelsSize->width())
6685 if (finalSize.width() > tickLabelsSize->width())
6686 tickLabelsSize->setWidth(finalSize.width());
6686 tickLabelsSize->setWidth(finalSize.width());
6687 if (finalSize.height() > tickLabelsSize->height())
6687 if (finalSize.height() > tickLabelsSize->height())
6688 tickLabelsSize->setHeight(finalSize.height());
6688 tickLabelsSize->setHeight(finalSize.height());
6689 }
6689 }
6690
6690
6691
6691
@@ -6838,24 +6838,24 void QCPAxisPainterPrivate::getMaxTickLa
6838 You probably want one of the subclasses like \ref QCPGraph or \ref QCPCurve instead.
6838 You probably want one of the subclasses like \ref QCPGraph or \ref QCPCurve instead.
6839 */
6839 */
6840 QCPAbstractPlottable::QCPAbstractPlottable(QCPAxis *keyAxis, QCPAxis *valueAxis) :
6840 QCPAbstractPlottable::QCPAbstractPlottable(QCPAxis *keyAxis, QCPAxis *valueAxis) :
6841 QCPLayerable(keyAxis->parentPlot(), QString(), keyAxis->axisRect()),
6841 QCPLayerable(keyAxis->parentPlot(), QString(), keyAxis->axisRect()),
6842 mName(),
6842 mName(),
6843 mAntialiasedFill(true),
6843 mAntialiasedFill(true),
6844 mAntialiasedScatters(true),
6844 mAntialiasedScatters(true),
6845 mAntialiasedErrorBars(false),
6845 mAntialiasedErrorBars(false),
6846 mPen(Qt::black),
6846 mPen(Qt::black),
6847 mSelectedPen(Qt::black),
6847 mSelectedPen(Qt::black),
6848 mBrush(Qt::NoBrush),
6848 mBrush(Qt::NoBrush),
6849 mSelectedBrush(Qt::NoBrush),
6849 mSelectedBrush(Qt::NoBrush),
6850 mKeyAxis(keyAxis),
6850 mKeyAxis(keyAxis),
6851 mValueAxis(valueAxis),
6851 mValueAxis(valueAxis),
6852 mSelectable(true),
6852 mSelectable(true),
6853 mSelected(false)
6853 mSelected(false)
6854 {
6854 {
6855 if (keyAxis->parentPlot() != valueAxis->parentPlot())
6855 if (keyAxis->parentPlot() != valueAxis->parentPlot())
6856 qDebug() << Q_FUNC_INFO << "Parent plot of keyAxis is not the same as that of valueAxis.";
6856 qDebug() << Q_FUNC_INFO << "Parent plot of keyAxis is not the same as that of valueAxis.";
6857 if (keyAxis->orientation() == valueAxis->orientation())
6857 if (keyAxis->orientation() == valueAxis->orientation())
6858 qDebug() << Q_FUNC_INFO << "keyAxis and valueAxis must be orthogonal to each other.";
6858 qDebug() << Q_FUNC_INFO << "keyAxis and valueAxis must be orthogonal to each other.";
6859 }
6859 }
6860
6860
6861 /*!
6861 /*!
@@ -6864,7 +6864,7 QCPAbstractPlottable::QCPAbstractPlottab
6864 */
6864 */
6865 void QCPAbstractPlottable::setName(const QString &name)
6865 void QCPAbstractPlottable::setName(const QString &name)
6866 {
6866 {
6867 mName = name;
6867 mName = name;
6868 }
6868 }
6869
6869
6870 /*!
6870 /*!
@@ -6875,7 +6875,7 void QCPAbstractPlottable::setName(const
6875 */
6875 */
6876 void QCPAbstractPlottable::setAntialiasedFill(bool enabled)
6876 void QCPAbstractPlottable::setAntialiasedFill(bool enabled)
6877 {
6877 {
6878 mAntialiasedFill = enabled;
6878 mAntialiasedFill = enabled;
6879 }
6879 }
6880
6880
6881 /*!
6881 /*!
@@ -6886,7 +6886,7 void QCPAbstractPlottable::setAntialiase
6886 */
6886 */
6887 void QCPAbstractPlottable::setAntialiasedScatters(bool enabled)
6887 void QCPAbstractPlottable::setAntialiasedScatters(bool enabled)
6888 {
6888 {
6889 mAntialiasedScatters = enabled;
6889 mAntialiasedScatters = enabled;
6890 }
6890 }
6891
6891
6892 /*!
6892 /*!
@@ -6897,7 +6897,7 void QCPAbstractPlottable::setAntialiase
6897 */
6897 */
6898 void QCPAbstractPlottable::setAntialiasedErrorBars(bool enabled)
6898 void QCPAbstractPlottable::setAntialiasedErrorBars(bool enabled)
6899 {
6899 {
6900 mAntialiasedErrorBars = enabled;
6900 mAntialiasedErrorBars = enabled;
6901 }
6901 }
6902
6902
6903
6903
@@ -6912,7 +6912,7 void QCPAbstractPlottable::setAntialiase
6912 */
6912 */
6913 void QCPAbstractPlottable::setPen(const QPen &pen)
6913 void QCPAbstractPlottable::setPen(const QPen &pen)
6914 {
6914 {
6915 mPen = pen;
6915 mPen = pen;
6916 }
6916 }
6917
6917
6918 /*!
6918 /*!
@@ -6923,7 +6923,7 void QCPAbstractPlottable::setPen(const
6923 */
6923 */
6924 void QCPAbstractPlottable::setSelectedPen(const QPen &pen)
6924 void QCPAbstractPlottable::setSelectedPen(const QPen &pen)
6925 {
6925 {
6926 mSelectedPen = pen;
6926 mSelectedPen = pen;
6927 }
6927 }
6928
6928
6929 /*!
6929 /*!
@@ -6937,7 +6937,7 void QCPAbstractPlottable::setSelectedPe
6937 */
6937 */
6938 void QCPAbstractPlottable::setBrush(const QBrush &brush)
6938 void QCPAbstractPlottable::setBrush(const QBrush &brush)
6939 {
6939 {
6940 mBrush = brush;
6940 mBrush = brush;
6941 }
6941 }
6942
6942
6943 /*!
6943 /*!
@@ -6948,7 +6948,7 void QCPAbstractPlottable::setBrush(cons
6948 */
6948 */
6949 void QCPAbstractPlottable::setSelectedBrush(const QBrush &brush)
6949 void QCPAbstractPlottable::setSelectedBrush(const QBrush &brush)
6950 {
6950 {
6951 mSelectedBrush = brush;
6951 mSelectedBrush = brush;
6952 }
6952 }
6953
6953
6954 /*!
6954 /*!
@@ -6964,7 +6964,7 void QCPAbstractPlottable::setSelectedBr
6964 */
6964 */
6965 void QCPAbstractPlottable::setKeyAxis(QCPAxis *axis)
6965 void QCPAbstractPlottable::setKeyAxis(QCPAxis *axis)
6966 {
6966 {
6967 mKeyAxis = axis;
6967 mKeyAxis = axis;
6968 }
6968 }
6969
6969
6970 /*!
6970 /*!
@@ -6980,7 +6980,7 void QCPAbstractPlottable::setKeyAxis(QC
6980 */
6980 */
6981 void QCPAbstractPlottable::setValueAxis(QCPAxis *axis)
6981 void QCPAbstractPlottable::setValueAxis(QCPAxis *axis)
6982 {
6982 {
6983 mValueAxis = axis;
6983 mValueAxis = axis;
6984 }
6984 }
6985
6985
6986 /*!
6986 /*!
@@ -6994,10 +6994,10 void QCPAbstractPlottable::setValueAxis(
6994 */
6994 */
6995 void QCPAbstractPlottable::setSelectable(bool selectable)
6995 void QCPAbstractPlottable::setSelectable(bool selectable)
6996 {
6996 {
6997 if (mSelectable != selectable)
6997 if (mSelectable != selectable)
6998 {
6998 {
6999 mSelectable = selectable;
6999 mSelectable = selectable;
7000 emit selectableChanged(mSelectable);
7000 emit selectableChanged(mSelectable);
7001 }
7001 }
7002 }
7002 }
7003
7003
@@ -7017,10 +7017,10 void QCPAbstractPlottable::setSelectable
7017 */
7017 */
7018 void QCPAbstractPlottable::setSelected(bool selected)
7018 void QCPAbstractPlottable::setSelected(bool selected)
7019 {
7019 {
7020 if (mSelected != selected)
7020 if (mSelected != selected)
7021 {
7021 {
7022 mSelected = selected;
7022 mSelected = selected;
7023 emit selectionChanged(mSelected);
7023 emit selectionChanged(mSelected);
7024 }
7024 }
7025 }
7025 }
7026
7026
@@ -7039,8 +7039,8 void QCPAbstractPlottable::setSelected(b
7039 */
7039 */
7040 void QCPAbstractPlottable::rescaleAxes(bool onlyEnlarge) const
7040 void QCPAbstractPlottable::rescaleAxes(bool onlyEnlarge) const
7041 {
7041 {
7042 rescaleKeyAxis(onlyEnlarge);
7042 rescaleKeyAxis(onlyEnlarge);
7043 rescaleValueAxis(onlyEnlarge);
7043 rescaleValueAxis(onlyEnlarge);
7044 }
7044 }
7045
7045
7046 /*!
7046 /*!
@@ -7050,33 +7050,33 void QCPAbstractPlottable::rescaleAxes(b
7050 */
7050 */
7051 void QCPAbstractPlottable::rescaleKeyAxis(bool onlyEnlarge) const
7051 void QCPAbstractPlottable::rescaleKeyAxis(bool onlyEnlarge) const
7052 {
7052 {
7053 QCPAxis *keyAxis = mKeyAxis.data();
7053 QCPAxis *keyAxis = mKeyAxis.data();
7054 if (!keyAxis) { qDebug() << Q_FUNC_INFO << "invalid key axis"; return; }
7054 if (!keyAxis) { qDebug() << Q_FUNC_INFO << "invalid key axis"; return; }
7055
7055
7056 SignDomain signDomain = sdBoth;
7056 SignDomain signDomain = sdBoth;
7057 if (keyAxis->scaleType() == QCPAxis::stLogarithmic)
7057 if (keyAxis->scaleType() == QCPAxis::stLogarithmic)
7058 signDomain = (keyAxis->range().upper < 0 ? sdNegative : sdPositive);
7058 signDomain = (keyAxis->range().upper < 0 ? sdNegative : sdPositive);
7059
7059
7060 bool foundRange;
7060 bool foundRange;
7061 QCPRange newRange = getKeyRange(foundRange, signDomain);
7061 QCPRange newRange = getKeyRange(foundRange, signDomain);
7062 if (foundRange)
7062 if (foundRange)
7063 {
7063 {
7064 if (onlyEnlarge)
7064 if (onlyEnlarge)
7065 newRange.expand(keyAxis->range());
7065 newRange.expand(keyAxis->range());
7066 if (!QCPRange::validRange(newRange)) // likely due to range being zero (plottable has only constant data in this axis dimension), shift current range to at least center the plottable
7066 if (!QCPRange::validRange(newRange)) // likely due to range being zero (plottable has only constant data in this axis dimension), shift current range to at least center the plottable
7067 {
7067 {
7068 double center = (newRange.lower+newRange.upper)*0.5; // upper and lower should be equal anyway, but just to make sure, incase validRange returned false for other reason
7068 double center = (newRange.lower+newRange.upper)*0.5; // upper and lower should be equal anyway, but just to make sure, incase validRange returned false for other reason
7069 if (keyAxis->scaleType() == QCPAxis::stLinear)
7069 if (keyAxis->scaleType() == QCPAxis::stLinear)
7070 {
7070 {
7071 newRange.lower = center-keyAxis->range().size()/2.0;
7071 newRange.lower = center-keyAxis->range().size()/2.0;
7072 newRange.upper = center+keyAxis->range().size()/2.0;
7072 newRange.upper = center+keyAxis->range().size()/2.0;
7073 } else // scaleType() == stLogarithmic
7073 } else // scaleType() == stLogarithmic
7074 {
7074 {
7075 newRange.lower = center/qSqrt(keyAxis->range().upper/keyAxis->range().lower);
7075 newRange.lower = center/qSqrt(keyAxis->range().upper/keyAxis->range().lower);
7076 newRange.upper = center*qSqrt(keyAxis->range().upper/keyAxis->range().lower);
7076 newRange.upper = center*qSqrt(keyAxis->range().upper/keyAxis->range().lower);
7077 }
7077 }
7078 }
7078 }
7079 keyAxis->setRange(newRange);
7079 keyAxis->setRange(newRange);
7080 }
7080 }
7081 }
7081 }
7082
7082
@@ -7090,33 +7090,33 void QCPAbstractPlottable::rescaleKeyAxi
7090 */
7090 */
7091 void QCPAbstractPlottable::rescaleValueAxis(bool onlyEnlarge) const
7091 void QCPAbstractPlottable::rescaleValueAxis(bool onlyEnlarge) const
7092 {
7092 {
7093 QCPAxis *valueAxis = mValueAxis.data();
7093 QCPAxis *valueAxis = mValueAxis.data();
7094 if (!valueAxis) { qDebug() << Q_FUNC_INFO << "invalid value axis"; return; }
7094 if (!valueAxis) { qDebug() << Q_FUNC_INFO << "invalid value axis"; return; }
7095
7095
7096 SignDomain signDomain = sdBoth;
7096 SignDomain signDomain = sdBoth;
7097 if (valueAxis->scaleType() == QCPAxis::stLogarithmic)
7097 if (valueAxis->scaleType() == QCPAxis::stLogarithmic)
7098 signDomain = (valueAxis->range().upper < 0 ? sdNegative : sdPositive);
7098 signDomain = (valueAxis->range().upper < 0 ? sdNegative : sdPositive);
7099
7099
7100 bool foundRange;
7100 bool foundRange;
7101 QCPRange newRange = getValueRange(foundRange, signDomain);
7101 QCPRange newRange = getValueRange(foundRange, signDomain);
7102 if (foundRange)
7102 if (foundRange)
7103 {
7103 {
7104 if (onlyEnlarge)
7104 if (onlyEnlarge)
7105 newRange.expand(valueAxis->range());
7105 newRange.expand(valueAxis->range());
7106 if (!QCPRange::validRange(newRange)) // likely due to range being zero (plottable has only constant data in this axis dimension), shift current range to at least center the plottable
7106 if (!QCPRange::validRange(newRange)) // likely due to range being zero (plottable has only constant data in this axis dimension), shift current range to at least center the plottable
7107 {
7107 {
7108 double center = (newRange.lower+newRange.upper)*0.5; // upper and lower should be equal anyway, but just to make sure, incase validRange returned false for other reason
7108 double center = (newRange.lower+newRange.upper)*0.5; // upper and lower should be equal anyway, but just to make sure, incase validRange returned false for other reason
7109 if (valueAxis->scaleType() == QCPAxis::stLinear)
7109 if (valueAxis->scaleType() == QCPAxis::stLinear)
7110 {
7110 {
7111 newRange.lower = center-valueAxis->range().size()/2.0;
7111 newRange.lower = center-valueAxis->range().size()/2.0;
7112 newRange.upper = center+valueAxis->range().size()/2.0;
7112 newRange.upper = center+valueAxis->range().size()/2.0;
7113 } else // scaleType() == stLogarithmic
7113 } else // scaleType() == stLogarithmic
7114 {
7114 {
7115 newRange.lower = center/qSqrt(valueAxis->range().upper/valueAxis->range().lower);
7115 newRange.lower = center/qSqrt(valueAxis->range().upper/valueAxis->range().lower);
7116 newRange.upper = center*qSqrt(valueAxis->range().upper/valueAxis->range().lower);
7116 newRange.upper = center*qSqrt(valueAxis->range().upper/valueAxis->range().lower);
7117 }
7117 }
7118 }
7118 }
7119 valueAxis->setRange(newRange);
7119 valueAxis->setRange(newRange);
7120 }
7120 }
7121 }
7121 }
7122
7122
@@ -7134,15 +7134,15 void QCPAbstractPlottable::rescaleValueA
7134 */
7134 */
7135 bool QCPAbstractPlottable::addToLegend()
7135 bool QCPAbstractPlottable::addToLegend()
7136 {
7136 {
7137 if (!mParentPlot || !mParentPlot->legend)
7137 if (!mParentPlot || !mParentPlot->legend)
7138 return false;
7138 return false;
7139
7139
7140 if (!mParentPlot->legend->hasItemWithPlottable(this))
7140 if (!mParentPlot->legend->hasItemWithPlottable(this))
7141 {
7141 {
7142 mParentPlot->legend->addItem(new QCPPlottableLegendItem(mParentPlot->legend, this));
7142 mParentPlot->legend->addItem(new QCPPlottableLegendItem(mParentPlot->legend, this));
7143 return true;
7143 return true;
7144 } else
7144 } else
7145 return false;
7145 return false;
7146 }
7146 }
7147
7147
7148 /*!
7148 /*!
@@ -7157,28 +7157,28 bool QCPAbstractPlottable::addToLegend()
7157 */
7157 */
7158 bool QCPAbstractPlottable::removeFromLegend() const
7158 bool QCPAbstractPlottable::removeFromLegend() const
7159 {
7159 {
7160 if (!mParentPlot->legend)
7160 if (!mParentPlot->legend)
7161 return false;
7161 return false;
7162
7162
7163 if (QCPPlottableLegendItem *lip = mParentPlot->legend->itemWithPlottable(this))
7163 if (QCPPlottableLegendItem *lip = mParentPlot->legend->itemWithPlottable(this))
7164 return mParentPlot->legend->removeItem(lip);
7164 return mParentPlot->legend->removeItem(lip);
7165 else
7165 else
7166 return false;
7166 return false;
7167 }
7167 }
7168
7168
7169 /* inherits documentation from base class */
7169 /* inherits documentation from base class */
7170 QRect QCPAbstractPlottable::clipRect() const
7170 QRect QCPAbstractPlottable::clipRect() const
7171 {
7171 {
7172 if (mKeyAxis && mValueAxis)
7172 if (mKeyAxis && mValueAxis)
7173 return mKeyAxis.data()->axisRect()->rect() & mValueAxis.data()->axisRect()->rect();
7173 return mKeyAxis.data()->axisRect()->rect() & mValueAxis.data()->axisRect()->rect();
7174 else
7174 else
7175 return QRect();
7175 return QRect();
7176 }
7176 }
7177
7177
7178 /* inherits documentation from base class */
7178 /* inherits documentation from base class */
7179 QCP::Interaction QCPAbstractPlottable::selectionCategory() const
7179 QCP::Interaction QCPAbstractPlottable::selectionCategory() const
7180 {
7180 {
7181 return QCP::iSelectPlottables;
7181 return QCP::iSelectPlottables;
7182 }
7182 }
7183
7183
7184 /*! \internal
7184 /*! \internal
@@ -7193,18 +7193,18 QCP::Interaction QCPAbstractPlottable::s
7193 */
7193 */
7194 void QCPAbstractPlottable::coordsToPixels(double key, double value, double &x, double &y) const
7194 void QCPAbstractPlottable::coordsToPixels(double key, double value, double &x, double &y) const
7195 {
7195 {
7196 QCPAxis *keyAxis = mKeyAxis.data();
7196 QCPAxis *keyAxis = mKeyAxis.data();
7197 QCPAxis *valueAxis = mValueAxis.data();
7197 QCPAxis *valueAxis = mValueAxis.data();
7198 if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
7198 if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
7199
7199
7200 if (keyAxis->orientation() == Qt::Horizontal)
7200 if (keyAxis->orientation() == Qt::Horizontal)
7201 {
7201 {
7202 x = keyAxis->coordToPixel(key);
7202 x = keyAxis->coordToPixel(key);
7203 y = valueAxis->coordToPixel(value);
7203 y = valueAxis->coordToPixel(value);
7204 } else
7204 } else
7205 {
7205 {
7206 y = keyAxis->coordToPixel(key);
7206 y = keyAxis->coordToPixel(key);
7207 x = valueAxis->coordToPixel(value);
7207 x = valueAxis->coordToPixel(value);
7208 }
7208 }
7209 }
7209 }
7210
7210
@@ -7215,14 +7215,14 void QCPAbstractPlottable::coordsToPixel
7215 */
7215 */
7216 const QPointF QCPAbstractPlottable::coordsToPixels(double key, double value) const
7216 const QPointF QCPAbstractPlottable::coordsToPixels(double key, double value) const
7217 {
7217 {
7218 QCPAxis *keyAxis = mKeyAxis.data();
7218 QCPAxis *keyAxis = mKeyAxis.data();
7219 QCPAxis *valueAxis = mValueAxis.data();
7219 QCPAxis *valueAxis = mValueAxis.data();
7220 if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return QPointF(); }
7220 if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return QPointF(); }
7221
7221
7222 if (keyAxis->orientation() == Qt::Horizontal)
7222 if (keyAxis->orientation() == Qt::Horizontal)
7223 return QPointF(keyAxis->coordToPixel(key), valueAxis->coordToPixel(value));
7223 return QPointF(keyAxis->coordToPixel(key), valueAxis->coordToPixel(value));
7224 else
7224 else
7225 return QPointF(valueAxis->coordToPixel(value), keyAxis->coordToPixel(key));
7225 return QPointF(valueAxis->coordToPixel(value), keyAxis->coordToPixel(key));
7226 }
7226 }
7227
7227
7228 /*! \internal
7228 /*! \internal
@@ -7237,18 +7237,18 const QPointF QCPAbstractPlottable::coor
7237 */
7237 */
7238 void QCPAbstractPlottable::pixelsToCoords(double x, double y, double &key, double &value) const
7238 void QCPAbstractPlottable::pixelsToCoords(double x, double y, double &key, double &value) const
7239 {
7239 {
7240 QCPAxis *keyAxis = mKeyAxis.data();
7240 QCPAxis *keyAxis = mKeyAxis.data();
7241 QCPAxis *valueAxis = mValueAxis.data();
7241 QCPAxis *valueAxis = mValueAxis.data();
7242 if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
7242 if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
7243
7243
7244 if (keyAxis->orientation() == Qt::Horizontal)
7244 if (keyAxis->orientation() == Qt::Horizontal)
7245 {
7245 {
7246 key = keyAxis->pixelToCoord(x);
7246 key = keyAxis->pixelToCoord(x);
7247 value = valueAxis->pixelToCoord(y);
7247 value = valueAxis->pixelToCoord(y);
7248 } else
7248 } else
7249 {
7249 {
7250 key = keyAxis->pixelToCoord(y);
7250 key = keyAxis->pixelToCoord(y);
7251 value = valueAxis->pixelToCoord(x);
7251 value = valueAxis->pixelToCoord(x);
7252 }
7252 }
7253 }
7253 }
7254
7254
@@ -7259,7 +7259,7 void QCPAbstractPlottable::pixelsToCoord
7259 */
7259 */
7260 void QCPAbstractPlottable::pixelsToCoords(const QPointF &pixelPos, double &key, double &value) const
7260 void QCPAbstractPlottable::pixelsToCoords(const QPointF &pixelPos, double &key, double &value) const
7261 {
7261 {
7262 pixelsToCoords(pixelPos.x(), pixelPos.y(), key, value);
7262 pixelsToCoords(pixelPos.x(), pixelPos.y(), key, value);
7263 }
7263 }
7264
7264
7265 /*! \internal
7265 /*! \internal
@@ -7269,7 +7269,7 void QCPAbstractPlottable::pixelsToCoord
7269 */
7269 */
7270 QPen QCPAbstractPlottable::mainPen() const
7270 QPen QCPAbstractPlottable::mainPen() const
7271 {
7271 {
7272 return mSelected ? mSelectedPen : mPen;
7272 return mSelected ? mSelectedPen : mPen;
7273 }
7273 }
7274
7274
7275 /*! \internal
7275 /*! \internal
@@ -7279,7 +7279,7 QPen QCPAbstractPlottable::mainPen() con
7279 */
7279 */
7280 QBrush QCPAbstractPlottable::mainBrush() const
7280 QBrush QCPAbstractPlottable::mainBrush() const
7281 {
7281 {
7282 return mSelected ? mSelectedBrush : mBrush;
7282 return mSelected ? mSelectedBrush : mBrush;
7283 }
7283 }
7284
7284
7285 /*! \internal
7285 /*! \internal
@@ -7297,7 +7297,7 QBrush QCPAbstractPlottable::mainBrush()
7297 */
7297 */
7298 void QCPAbstractPlottable::applyDefaultAntialiasingHint(QCPPainter *painter) const
7298 void QCPAbstractPlottable::applyDefaultAntialiasingHint(QCPPainter *painter) const
7299 {
7299 {
7300 applyAntialiasingHint(painter, mAntialiased, QCP::aePlottables);
7300 applyAntialiasingHint(painter, mAntialiased, QCP::aePlottables);
7301 }
7301 }
7302
7302
7303 /*! \internal
7303 /*! \internal
@@ -7313,7 +7313,7 void QCPAbstractPlottable::applyDefaultA
7313 */
7313 */
7314 void QCPAbstractPlottable::applyFillAntialiasingHint(QCPPainter *painter) const
7314 void QCPAbstractPlottable::applyFillAntialiasingHint(QCPPainter *painter) const
7315 {
7315 {
7316 applyAntialiasingHint(painter, mAntialiasedFill, QCP::aeFills);
7316 applyAntialiasingHint(painter, mAntialiasedFill, QCP::aeFills);
7317 }
7317 }
7318
7318
7319 /*! \internal
7319 /*! \internal
@@ -7329,7 +7329,7 void QCPAbstractPlottable::applyFillAnti
7329 */
7329 */
7330 void QCPAbstractPlottable::applyScattersAntialiasingHint(QCPPainter *painter) const
7330 void QCPAbstractPlottable::applyScattersAntialiasingHint(QCPPainter *painter) const
7331 {
7331 {
7332 applyAntialiasingHint(painter, mAntialiasedScatters, QCP::aeScatters);
7332 applyAntialiasingHint(painter, mAntialiasedScatters, QCP::aeScatters);
7333 }
7333 }
7334
7334
7335 /*! \internal
7335 /*! \internal
@@ -7345,7 +7345,7 void QCPAbstractPlottable::applyScatters
7345 */
7345 */
7346 void QCPAbstractPlottable::applyErrorBarsAntialiasingHint(QCPPainter *painter) const
7346 void QCPAbstractPlottable::applyErrorBarsAntialiasingHint(QCPPainter *painter) const
7347 {
7347 {
7348 applyAntialiasingHint(painter, mAntialiasedErrorBars, QCP::aeErrorBars);
7348 applyAntialiasingHint(painter, mAntialiasedErrorBars, QCP::aeErrorBars);
7349 }
7349 }
7350
7350
7351 /*! \internal
7351 /*! \internal
@@ -7360,48 +7360,48 void QCPAbstractPlottable::applyErrorBar
7360 */
7360 */
7361 double QCPAbstractPlottable::distSqrToLine(const QPointF &start, const QPointF &end, const QPointF &point) const
7361 double QCPAbstractPlottable::distSqrToLine(const QPointF &start, const QPointF &end, const QPointF &point) const
7362 {
7362 {
7363 QVector2D a(start);
7363 QVector2D a(start);
7364 QVector2D b(end);
7364 QVector2D b(end);
7365 QVector2D p(point);
7365 QVector2D p(point);
7366 QVector2D v(b-a);
7366 QVector2D v(b-a);
7367
7367
7368 double vLengthSqr = v.lengthSquared();
7368 double vLengthSqr = v.lengthSquared();
7369 if (!qFuzzyIsNull(vLengthSqr))
7369 if (!qFuzzyIsNull(vLengthSqr))
7370 {
7370 {
7371 double mu = QVector2D::dotProduct(p-a, v)/vLengthSqr;
7371 double mu = QVector2D::dotProduct(p-a, v)/vLengthSqr;
7372 if (mu < 0)
7372 if (mu < 0)
7373 return (a-p).lengthSquared();
7374 else if (mu > 1)
7375 return (b-p).lengthSquared();
7376 else
7377 return ((a + mu*v)-p).lengthSquared();
7378 } else
7373 return (a-p).lengthSquared();
7379 return (a-p).lengthSquared();
7374 else if (mu > 1)
7375 return (b-p).lengthSquared();
7376 else
7377 return ((a + mu*v)-p).lengthSquared();
7378 } else
7379 return (a-p).lengthSquared();
7380 }
7380 }
7381
7381
7382 /* inherits documentation from base class */
7382 /* inherits documentation from base class */
7383 void QCPAbstractPlottable::selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged)
7383 void QCPAbstractPlottable::selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged)
7384 {
7384 {
7385 Q_UNUSED(event)
7385 Q_UNUSED(event)
7386 Q_UNUSED(details)
7386 Q_UNUSED(details)
7387 if (mSelectable)
7387 if (mSelectable)
7388 {
7388 {
7389 bool selBefore = mSelected;
7389 bool selBefore = mSelected;
7390 setSelected(additive ? !mSelected : true);
7390 setSelected(additive ? !mSelected : true);
7391 if (selectionStateChanged)
7391 if (selectionStateChanged)
7392 *selectionStateChanged = mSelected != selBefore;
7392 *selectionStateChanged = mSelected != selBefore;
7393 }
7393 }
7394 }
7394 }
7395
7395
7396 /* inherits documentation from base class */
7396 /* inherits documentation from base class */
7397 void QCPAbstractPlottable::deselectEvent(bool *selectionStateChanged)
7397 void QCPAbstractPlottable::deselectEvent(bool *selectionStateChanged)
7398 {
7398 {
7399 if (mSelectable)
7399 if (mSelectable)
7400 {
7400 {
7401 bool selBefore = mSelected;
7401 bool selBefore = mSelected;
7402 setSelected(false);
7402 setSelected(false);
7403 if (selectionStateChanged)
7403 if (selectionStateChanged)
7404 *selectionStateChanged = mSelected != selBefore;
7404 *selectionStateChanged = mSelected != selBefore;
7405 }
7405 }
7406 }
7406 }
7407
7407
@@ -7451,25 +7451,25 void QCPAbstractPlottable::deselectEvent
7451 explained in the subclassing section of the QCPAbstractItem documentation.
7451 explained in the subclassing section of the QCPAbstractItem documentation.
7452 */
7452 */
7453 QCPItemAnchor::QCPItemAnchor(QCustomPlot *parentPlot, QCPAbstractItem *parentItem, const QString name, int anchorId) :
7453 QCPItemAnchor::QCPItemAnchor(QCustomPlot *parentPlot, QCPAbstractItem *parentItem, const QString name, int anchorId) :
7454 mName(name),
7454 mName(name),
7455 mParentPlot(parentPlot),
7455 mParentPlot(parentPlot),
7456 mParentItem(parentItem),
7456 mParentItem(parentItem),
7457 mAnchorId(anchorId)
7457 mAnchorId(anchorId)
7458 {
7458 {
7459 }
7459 }
7460
7460
7461 QCPItemAnchor::~QCPItemAnchor()
7461 QCPItemAnchor::~QCPItemAnchor()
7462 {
7462 {
7463 // unregister as parent at children:
7463 // unregister as parent at children:
7464 foreach (QCPItemPosition *child, mChildrenX.toList())
7464 foreach (QCPItemPosition *child, mChildrenX.toList())
7465 {
7465 {
7466 if (child->parentAnchorX() == this)
7466 if (child->parentAnchorX() == this)
7467 child->setParentAnchorX(0); // this acts back on this anchor and child removes itself from mChildrenX
7467 child->setParentAnchorX(0); // this acts back on this anchor and child removes itself from mChildrenX
7468 }
7468 }
7469 foreach (QCPItemPosition *child, mChildrenY.toList())
7469 foreach (QCPItemPosition *child, mChildrenY.toList())
7470 {
7470 {
7471 if (child->parentAnchorY() == this)
7471 if (child->parentAnchorY() == this)
7472 child->setParentAnchorY(0); // this acts back on this anchor and child removes itself from mChildrenY
7472 child->setParentAnchorY(0); // this acts back on this anchor and child removes itself from mChildrenY
7473 }
7473 }
7474 }
7474 }
7475
7475
@@ -7481,20 +7481,20 QCPItemAnchor::~QCPItemAnchor()
7481 */
7481 */
7482 QPointF QCPItemAnchor::pixelPoint() const
7482 QPointF QCPItemAnchor::pixelPoint() const
7483 {
7483 {
7484 if (mParentItem)
7484 if (mParentItem)
7485 {
7485 {
7486 if (mAnchorId > -1)
7486 if (mAnchorId > -1)
7487 {
7487 {
7488 return mParentItem->anchorPixelPoint(mAnchorId);
7488 return mParentItem->anchorPixelPoint(mAnchorId);
7489 } else
7489 } else
7490 {
7490 {
7491 qDebug() << Q_FUNC_INFO << "no valid anchor id set:" << mAnchorId;
7491 qDebug() << Q_FUNC_INFO << "no valid anchor id set:" << mAnchorId;
7492 return QPointF();
7492 return QPointF();
7493 }
7493 }
7494 } else
7494 } else
7495 {
7495 {
7496 qDebug() << Q_FUNC_INFO << "no parent item set";
7496 qDebug() << Q_FUNC_INFO << "no parent item set";
7497 return QPointF();
7497 return QPointF();
7498 }
7498 }
7499 }
7499 }
7500
7500
@@ -7508,10 +7508,10 QPointF QCPItemAnchor::pixelPoint() cons
7508 */
7508 */
7509 void QCPItemAnchor::addChildX(QCPItemPosition *pos)
7509 void QCPItemAnchor::addChildX(QCPItemPosition *pos)
7510 {
7510 {
7511 if (!mChildrenX.contains(pos))
7511 if (!mChildrenX.contains(pos))
7512 mChildrenX.insert(pos);
7512 mChildrenX.insert(pos);
7513 else
7513 else
7514 qDebug() << Q_FUNC_INFO << "provided pos is child already" << reinterpret_cast<quintptr>(pos);
7514 qDebug() << Q_FUNC_INFO << "provided pos is child already" << reinterpret_cast<quintptr>(pos);
7515 }
7515 }
7516
7516
7517 /*! \internal
7517 /*! \internal
@@ -7522,8 +7522,8 void QCPItemAnchor::addChildX(QCPItemPos
7522 */
7522 */
7523 void QCPItemAnchor::removeChildX(QCPItemPosition *pos)
7523 void QCPItemAnchor::removeChildX(QCPItemPosition *pos)
7524 {
7524 {
7525 if (!mChildrenX.remove(pos))
7525 if (!mChildrenX.remove(pos))
7526 qDebug() << Q_FUNC_INFO << "provided pos isn't child" << reinterpret_cast<quintptr>(pos);
7526 qDebug() << Q_FUNC_INFO << "provided pos isn't child" << reinterpret_cast<quintptr>(pos);
7527 }
7527 }
7528
7528
7529 /*! \internal
7529 /*! \internal
@@ -7536,10 +7536,10 void QCPItemAnchor::removeChildX(QCPItem
7536 */
7536 */
7537 void QCPItemAnchor::addChildY(QCPItemPosition *pos)
7537 void QCPItemAnchor::addChildY(QCPItemPosition *pos)
7538 {
7538 {
7539 if (!mChildrenY.contains(pos))
7539 if (!mChildrenY.contains(pos))
7540 mChildrenY.insert(pos);
7540 mChildrenY.insert(pos);
7541 else
7541 else
7542 qDebug() << Q_FUNC_INFO << "provided pos is child already" << reinterpret_cast<quintptr>(pos);
7542 qDebug() << Q_FUNC_INFO << "provided pos is child already" << reinterpret_cast<quintptr>(pos);
7543 }
7543 }
7544
7544
7545 /*! \internal
7545 /*! \internal
@@ -7550,8 +7550,8 void QCPItemAnchor::addChildY(QCPItemPos
7550 */
7550 */
7551 void QCPItemAnchor::removeChildY(QCPItemPosition *pos)
7551 void QCPItemAnchor::removeChildY(QCPItemPosition *pos)
7552 {
7552 {
7553 if (!mChildrenY.remove(pos))
7553 if (!mChildrenY.remove(pos))
7554 qDebug() << Q_FUNC_INFO << "provided pos isn't child" << reinterpret_cast<quintptr>(pos);
7554 qDebug() << Q_FUNC_INFO << "provided pos isn't child" << reinterpret_cast<quintptr>(pos);
7555 }
7555 }
7556
7556
7557
7557
@@ -7624,42 +7624,42 void QCPItemAnchor::removeChildY(QCPItem
7624 explained in the subclassing section of the QCPAbstractItem documentation.
7624 explained in the subclassing section of the QCPAbstractItem documentation.
7625 */
7625 */
7626 QCPItemPosition::QCPItemPosition(QCustomPlot *parentPlot, QCPAbstractItem *parentItem, const QString name) :
7626 QCPItemPosition::QCPItemPosition(QCustomPlot *parentPlot, QCPAbstractItem *parentItem, const QString name) :
7627 QCPItemAnchor(parentPlot, parentItem, name),
7627 QCPItemAnchor(parentPlot, parentItem, name),
7628 mPositionTypeX(ptAbsolute),
7628 mPositionTypeX(ptAbsolute),
7629 mPositionTypeY(ptAbsolute),
7629 mPositionTypeY(ptAbsolute),
7630 mKey(0),
7630 mKey(0),
7631 mValue(0),
7631 mValue(0),
7632 mParentAnchorX(0),
7632 mParentAnchorX(0),
7633 mParentAnchorY(0)
7633 mParentAnchorY(0)
7634 {
7634 {
7635 }
7635 }
7636
7636
7637 QCPItemPosition::~QCPItemPosition()
7637 QCPItemPosition::~QCPItemPosition()
7638 {
7638 {
7639 // unregister as parent at children:
7639 // unregister as parent at children:
7640 // Note: this is done in ~QCPItemAnchor again, but it's important QCPItemPosition does it itself, because only then
7640 // Note: this is done in ~QCPItemAnchor again, but it's important QCPItemPosition does it itself, because only then
7641 // the setParentAnchor(0) call the correct QCPItemPosition::pixelPoint function instead of QCPItemAnchor::pixelPoint
7641 // the setParentAnchor(0) call the correct QCPItemPosition::pixelPoint function instead of QCPItemAnchor::pixelPoint
7642 foreach (QCPItemPosition *child, mChildrenX.toList())
7642 foreach (QCPItemPosition *child, mChildrenX.toList())
7643 {
7643 {
7644 if (child->parentAnchorX() == this)
7644 if (child->parentAnchorX() == this)
7645 child->setParentAnchorX(0); // this acts back on this anchor and child removes itself from mChildrenX
7645 child->setParentAnchorX(0); // this acts back on this anchor and child removes itself from mChildrenX
7646 }
7646 }
7647 foreach (QCPItemPosition *child, mChildrenY.toList())
7647 foreach (QCPItemPosition *child, mChildrenY.toList())
7648 {
7648 {
7649 if (child->parentAnchorY() == this)
7649 if (child->parentAnchorY() == this)
7650 child->setParentAnchorY(0); // this acts back on this anchor and child removes itself from mChildrenY
7650 child->setParentAnchorY(0); // this acts back on this anchor and child removes itself from mChildrenY
7651 }
7651 }
7652 // unregister as child in parent:
7652 // unregister as child in parent:
7653 if (mParentAnchorX)
7653 if (mParentAnchorX)
7654 mParentAnchorX->removeChildX(this);
7654 mParentAnchorX->removeChildX(this);
7655 if (mParentAnchorY)
7655 if (mParentAnchorY)
7656 mParentAnchorY->removeChildY(this);
7656 mParentAnchorY->removeChildY(this);
7657 }
7657 }
7658
7658
7659 /* can't make this a header inline function, because QPointer breaks with forward declared types, see QTBUG-29588 */
7659 /* can't make this a header inline function, because QPointer breaks with forward declared types, see QTBUG-29588 */
7660 QCPAxisRect *QCPItemPosition::axisRect() const
7660 QCPAxisRect *QCPItemPosition::axisRect() const
7661 {
7661 {
7662 return mAxisRect.data();
7662 return mAxisRect.data();
7663 }
7663 }
7664
7664
7665 /*!
7665 /*!
@@ -7689,8 +7689,8 QCPAxisRect *QCPItemPosition::axisRect()
7689 */
7689 */
7690 void QCPItemPosition::setType(QCPItemPosition::PositionType type)
7690 void QCPItemPosition::setType(QCPItemPosition::PositionType type)
7691 {
7691 {
7692 setTypeX(type);
7692 setTypeX(type);
7693 setTypeY(type);
7693 setTypeY(type);
7694 }
7694 }
7695
7695
7696 /*!
7696 /*!
@@ -7702,24 +7702,24 void QCPItemPosition::setType(QCPItemPos
7702 */
7702 */
7703 void QCPItemPosition::setTypeX(QCPItemPosition::PositionType type)
7703 void QCPItemPosition::setTypeX(QCPItemPosition::PositionType type)
7704 {
7704 {
7705 if (mPositionTypeX != type)
7705 if (mPositionTypeX != type)
7706 {
7706 {
7707 // if switching from or to coordinate type that isn't valid (e.g. because axes or axis rect
7707 // if switching from or to coordinate type that isn't valid (e.g. because axes or axis rect
7708 // were deleted), don't try to recover the pixelPoint() because it would output a qDebug warning.
7708 // were deleted), don't try to recover the pixelPoint() because it would output a qDebug warning.
7709 bool retainPixelPosition = true;
7709 bool retainPixelPosition = true;
7710 if ((mPositionTypeX == ptPlotCoords || type == ptPlotCoords) && (!mKeyAxis || !mValueAxis))
7710 if ((mPositionTypeX == ptPlotCoords || type == ptPlotCoords) && (!mKeyAxis || !mValueAxis))
7711 retainPixelPosition = false;
7711 retainPixelPosition = false;
7712 if ((mPositionTypeX == ptAxisRectRatio || type == ptAxisRectRatio) && (!mAxisRect))
7712 if ((mPositionTypeX == ptAxisRectRatio || type == ptAxisRectRatio) && (!mAxisRect))
7713 retainPixelPosition = false;
7713 retainPixelPosition = false;
7714
7714
7715 QPointF pixel;
7715 QPointF pixel;
7716 if (retainPixelPosition)
7716 if (retainPixelPosition)
7717 pixel = pixelPoint();
7717 pixel = pixelPoint();
7718
7718
7719 mPositionTypeX = type;
7719 mPositionTypeX = type;
7720
7720
7721 if (retainPixelPosition)
7721 if (retainPixelPosition)
7722 setPixelPoint(pixel);
7722 setPixelPoint(pixel);
7723 }
7723 }
7724 }
7724 }
7725
7725
@@ -7732,24 +7732,24 void QCPItemPosition::setTypeX(QCPItemPo
7732 */
7732 */
7733 void QCPItemPosition::setTypeY(QCPItemPosition::PositionType type)
7733 void QCPItemPosition::setTypeY(QCPItemPosition::PositionType type)
7734 {
7734 {
7735 if (mPositionTypeY != type)
7735 if (mPositionTypeY != type)
7736 {
7736 {
7737 // if switching from or to coordinate type that isn't valid (e.g. because axes or axis rect
7737 // if switching from or to coordinate type that isn't valid (e.g. because axes or axis rect
7738 // were deleted), don't try to recover the pixelPoint() because it would output a qDebug warning.
7738 // were deleted), don't try to recover the pixelPoint() because it would output a qDebug warning.
7739 bool retainPixelPosition = true;
7739 bool retainPixelPosition = true;
7740 if ((mPositionTypeY == ptPlotCoords || type == ptPlotCoords) && (!mKeyAxis || !mValueAxis))
7740 if ((mPositionTypeY == ptPlotCoords || type == ptPlotCoords) && (!mKeyAxis || !mValueAxis))
7741 retainPixelPosition = false;
7741 retainPixelPosition = false;
7742 if ((mPositionTypeY == ptAxisRectRatio || type == ptAxisRectRatio) && (!mAxisRect))
7742 if ((mPositionTypeY == ptAxisRectRatio || type == ptAxisRectRatio) && (!mAxisRect))
7743 retainPixelPosition = false;
7743 retainPixelPosition = false;
7744
7744
7745 QPointF pixel;
7745 QPointF pixel;
7746 if (retainPixelPosition)
7746 if (retainPixelPosition)
7747 pixel = pixelPoint();
7747 pixel = pixelPoint();
7748
7748
7749 mPositionTypeY = type;
7749 mPositionTypeY = type;
7750
7750
7751 if (retainPixelPosition)
7751 if (retainPixelPosition)
7752 setPixelPoint(pixel);
7752 setPixelPoint(pixel);
7753 }
7753 }
7754 }
7754 }
7755
7755
@@ -7773,9 +7773,9 void QCPItemPosition::setTypeY(QCPItemPo
7773 */
7773 */
7774 bool QCPItemPosition::setParentAnchor(QCPItemAnchor *parentAnchor, bool keepPixelPosition)
7774 bool QCPItemPosition::setParentAnchor(QCPItemAnchor *parentAnchor, bool keepPixelPosition)
7775 {
7775 {
7776 bool successX = setParentAnchorX(parentAnchor, keepPixelPosition);
7776 bool successX = setParentAnchorX(parentAnchor, keepPixelPosition);
7777 bool successY = setParentAnchorY(parentAnchor, keepPixelPosition);
7777 bool successY = setParentAnchorY(parentAnchor, keepPixelPosition);
7778 return successX && successY;
7778 return successX && successY;
7779 }
7779 }
7780
7780
7781 /*!
7781 /*!
@@ -7787,60 +7787,60 bool QCPItemPosition::setParentAnchor(QC
7787 */
7787 */
7788 bool QCPItemPosition::setParentAnchorX(QCPItemAnchor *parentAnchor, bool keepPixelPosition)
7788 bool QCPItemPosition::setParentAnchorX(QCPItemAnchor *parentAnchor, bool keepPixelPosition)
7789 {
7789 {
7790 // make sure self is not assigned as parent:
7790 // make sure self is not assigned as parent:
7791 if (parentAnchor == this)
7791 if (parentAnchor == this)
7792 {
7792 {
7793 qDebug() << Q_FUNC_INFO << "can't set self as parent anchor" << reinterpret_cast<quintptr>(parentAnchor);
7793 qDebug() << Q_FUNC_INFO << "can't set self as parent anchor" << reinterpret_cast<quintptr>(parentAnchor);
7794 return false;
7794 return false;
7795 }
7795 }
7796 // make sure no recursive parent-child-relationships are created:
7796 // make sure no recursive parent-child-relationships are created:
7797 QCPItemAnchor *currentParent = parentAnchor;
7797 QCPItemAnchor *currentParent = parentAnchor;
7798 while (currentParent)
7798 while (currentParent)
7799 {
7799 {
7800 if (QCPItemPosition *currentParentPos = currentParent->toQCPItemPosition())
7800 if (QCPItemPosition *currentParentPos = currentParent->toQCPItemPosition())
7801 {
7801 {
7802 // is a QCPItemPosition, might have further parent, so keep iterating
7802 // is a QCPItemPosition, might have further parent, so keep iterating
7803 if (currentParentPos == this)
7803 if (currentParentPos == this)
7804 {
7804 {
7805 qDebug() << Q_FUNC_INFO << "can't create recursive parent-child-relationship" << reinterpret_cast<quintptr>(parentAnchor);
7805 qDebug() << Q_FUNC_INFO << "can't create recursive parent-child-relationship" << reinterpret_cast<quintptr>(parentAnchor);
7806 return false;
7806 return false;
7807 }
7807 }
7808 currentParent = currentParentPos->parentAnchorX();
7808 currentParent = currentParentPos->parentAnchorX();
7809 } else
7809 } else
7810 {
7810 {
7811 // is a QCPItemAnchor, can't have further parent. Now make sure the parent items aren't the
7811 // is a QCPItemAnchor, can't have further parent. Now make sure the parent items aren't the
7812 // same, to prevent a position being child of an anchor which itself depends on the position,
7812 // same, to prevent a position being child of an anchor which itself depends on the position,
7813 // because they're both on the same item:
7813 // because they're both on the same item:
7814 if (currentParent->mParentItem == mParentItem)
7814 if (currentParent->mParentItem == mParentItem)
7815 {
7815 {
7816 qDebug() << Q_FUNC_INFO << "can't set parent to be an anchor which itself depends on this position" << reinterpret_cast<quintptr>(parentAnchor);
7816 qDebug() << Q_FUNC_INFO << "can't set parent to be an anchor which itself depends on this position" << reinterpret_cast<quintptr>(parentAnchor);
7817 return false;
7817 return false;
7818 }
7818 }
7819 break;
7819 break;
7820 }
7820 }
7821 }
7821 }
7822
7822
7823 // if previously no parent set and PosType is still ptPlotCoords, set to ptAbsolute:
7823 // if previously no parent set and PosType is still ptPlotCoords, set to ptAbsolute:
7824 if (!mParentAnchorX && mPositionTypeX == ptPlotCoords)
7824 if (!mParentAnchorX && mPositionTypeX == ptPlotCoords)
7825 setTypeX(ptAbsolute);
7825 setTypeX(ptAbsolute);
7826
7826
7827 // save pixel position:
7827 // save pixel position:
7828 QPointF pixelP;
7828 QPointF pixelP;
7829 if (keepPixelPosition)
7829 if (keepPixelPosition)
7830 pixelP = pixelPoint();
7830 pixelP = pixelPoint();
7831 // unregister at current parent anchor:
7831 // unregister at current parent anchor:
7832 if (mParentAnchorX)
7832 if (mParentAnchorX)
7833 mParentAnchorX->removeChildX(this);
7833 mParentAnchorX->removeChildX(this);
7834 // register at new parent anchor:
7834 // register at new parent anchor:
7835 if (parentAnchor)
7835 if (parentAnchor)
7836 parentAnchor->addChildX(this);
7836 parentAnchor->addChildX(this);
7837 mParentAnchorX = parentAnchor;
7837 mParentAnchorX = parentAnchor;
7838 // restore pixel position under new parent:
7838 // restore pixel position under new parent:
7839 if (keepPixelPosition)
7839 if (keepPixelPosition)
7840 setPixelPoint(pixelP);
7840 setPixelPoint(pixelP);
7841 else
7841 else
7842 setCoords(0, coords().y());
7842 setCoords(0, coords().y());
7843 return true;
7843 return true;
7844 }
7844 }
7845
7845
7846 /*!
7846 /*!
@@ -7852,60 +7852,60 bool QCPItemPosition::setParentAnchorX(Q
7852 */
7852 */
7853 bool QCPItemPosition::setParentAnchorY(QCPItemAnchor *parentAnchor, bool keepPixelPosition)
7853 bool QCPItemPosition::setParentAnchorY(QCPItemAnchor *parentAnchor, bool keepPixelPosition)
7854 {
7854 {
7855 // make sure self is not assigned as parent:
7855 // make sure self is not assigned as parent:
7856 if (parentAnchor == this)
7856 if (parentAnchor == this)
7857 {
7857 {
7858 qDebug() << Q_FUNC_INFO << "can't set self as parent anchor" << reinterpret_cast<quintptr>(parentAnchor);
7858 qDebug() << Q_FUNC_INFO << "can't set self as parent anchor" << reinterpret_cast<quintptr>(parentAnchor);
7859 return false;
7859 return false;
7860 }
7860 }
7861 // make sure no recursive parent-child-relationships are created:
7861 // make sure no recursive parent-child-relationships are created:
7862 QCPItemAnchor *currentParent = parentAnchor;
7862 QCPItemAnchor *currentParent = parentAnchor;
7863 while (currentParent)
7863 while (currentParent)
7864 {
7864 {
7865 if (QCPItemPosition *currentParentPos = currentParent->toQCPItemPosition())
7865 if (QCPItemPosition *currentParentPos = currentParent->toQCPItemPosition())
7866 {
7866 {
7867 // is a QCPItemPosition, might have further parent, so keep iterating
7867 // is a QCPItemPosition, might have further parent, so keep iterating
7868 if (currentParentPos == this)
7868 if (currentParentPos == this)
7869 {
7869 {
7870 qDebug() << Q_FUNC_INFO << "can't create recursive parent-child-relationship" << reinterpret_cast<quintptr>(parentAnchor);
7870 qDebug() << Q_FUNC_INFO << "can't create recursive parent-child-relationship" << reinterpret_cast<quintptr>(parentAnchor);
7871 return false;
7871 return false;
7872 }
7872 }
7873 currentParent = currentParentPos->parentAnchorY();
7873 currentParent = currentParentPos->parentAnchorY();
7874 } else
7874 } else
7875 {
7875 {
7876 // is a QCPItemAnchor, can't have further parent. Now make sure the parent items aren't the
7876 // is a QCPItemAnchor, can't have further parent. Now make sure the parent items aren't the
7877 // same, to prevent a position being child of an anchor which itself depends on the position,
7877 // same, to prevent a position being child of an anchor which itself depends on the position,
7878 // because they're both on the same item:
7878 // because they're both on the same item:
7879 if (currentParent->mParentItem == mParentItem)
7879 if (currentParent->mParentItem == mParentItem)
7880 {
7880 {
7881 qDebug() << Q_FUNC_INFO << "can't set parent to be an anchor which itself depends on this position" << reinterpret_cast<quintptr>(parentAnchor);
7881 qDebug() << Q_FUNC_INFO << "can't set parent to be an anchor which itself depends on this position" << reinterpret_cast<quintptr>(parentAnchor);
7882 return false;
7882 return false;
7883 }
7883 }
7884 break;
7884 break;
7885 }
7885 }
7886 }
7886 }
7887
7887
7888 // if previously no parent set and PosType is still ptPlotCoords, set to ptAbsolute:
7888 // if previously no parent set and PosType is still ptPlotCoords, set to ptAbsolute:
7889 if (!mParentAnchorY && mPositionTypeY == ptPlotCoords)
7889 if (!mParentAnchorY && mPositionTypeY == ptPlotCoords)
7890 setTypeY(ptAbsolute);
7890 setTypeY(ptAbsolute);
7891
7891
7892 // save pixel position:
7892 // save pixel position:
7893 QPointF pixelP;
7893 QPointF pixelP;
7894 if (keepPixelPosition)
7894 if (keepPixelPosition)
7895 pixelP = pixelPoint();
7895 pixelP = pixelPoint();
7896 // unregister at current parent anchor:
7896 // unregister at current parent anchor:
7897 if (mParentAnchorY)
7897 if (mParentAnchorY)
7898 mParentAnchorY->removeChildY(this);
7898 mParentAnchorY->removeChildY(this);
7899 // register at new parent anchor:
7899 // register at new parent anchor:
7900 if (parentAnchor)
7900 if (parentAnchor)
7901 parentAnchor->addChildY(this);
7901 parentAnchor->addChildY(this);
7902 mParentAnchorY = parentAnchor;
7902 mParentAnchorY = parentAnchor;
7903 // restore pixel position under new parent:
7903 // restore pixel position under new parent:
7904 if (keepPixelPosition)
7904 if (keepPixelPosition)
7905 setPixelPoint(pixelP);
7905 setPixelPoint(pixelP);
7906 else
7906 else
7907 setCoords(coords().x(), 0);
7907 setCoords(coords().x(), 0);
7908 return true;
7908 return true;
7909 }
7909 }
7910
7910
7911 /*!
7911 /*!
@@ -7927,8 +7927,8 bool QCPItemPosition::setParentAnchorY(Q
7927 */
7927 */
7928 void QCPItemPosition::setCoords(double key, double value)
7928 void QCPItemPosition::setCoords(double key, double value)
7929 {
7929 {
7930 mKey = key;
7930 mKey = key;
7931 mValue = value;
7931 mValue = value;
7932 }
7932 }
7933
7933
7934 /*! \overload
7934 /*! \overload
@@ -7938,7 +7938,7 void QCPItemPosition::setCoords(double k
7938 */
7938 */
7939 void QCPItemPosition::setCoords(const QPointF &pos)
7939 void QCPItemPosition::setCoords(const QPointF &pos)
7940 {
7940 {
7941 setCoords(pos.x(), pos.y());
7941 setCoords(pos.x(), pos.y());
7942 }
7942 }
7943
7943
7944 /*!
7944 /*!
@@ -7949,97 +7949,97 void QCPItemPosition::setCoords(const QP
7949 */
7949 */
7950 QPointF QCPItemPosition::pixelPoint() const
7950 QPointF QCPItemPosition::pixelPoint() const
7951 {
7951 {
7952 QPointF result;
7952 QPointF result;
7953
7953
7954 // determine X:
7954 // determine X:
7955 switch (mPositionTypeX)
7955 switch (mPositionTypeX)
7956 {
7956 {
7957 case ptAbsolute:
7957 case ptAbsolute:
7958 {
7958 {
7959 result.rx() = mKey;
7959 result.rx() = mKey;
7960 if (mParentAnchorX)
7960 if (mParentAnchorX)
7961 result.rx() += mParentAnchorX->pixelPoint().x();
7961 result.rx() += mParentAnchorX->pixelPoint().x();
7962 break;
7962 break;
7963 }
7963 }
7964 case ptViewportRatio:
7964 case ptViewportRatio:
7965 {
7965 {
7966 result.rx() = mKey*mParentPlot->viewport().width();
7966 result.rx() = mKey*mParentPlot->viewport().width();
7967 if (mParentAnchorX)
7967 if (mParentAnchorX)
7968 result.rx() += mParentAnchorX->pixelPoint().x();
7968 result.rx() += mParentAnchorX->pixelPoint().x();
7969 else
7969 else
7970 result.rx() += mParentPlot->viewport().left();
7970 result.rx() += mParentPlot->viewport().left();
7971 break;
7971 break;
7972 }
7972 }
7973 case ptAxisRectRatio:
7973 case ptAxisRectRatio:
7974 {
7974 {
7975 if (mAxisRect)
7975 if (mAxisRect)
7976 {
7976 {
7977 result.rx() = mKey*mAxisRect.data()->width();
7977 result.rx() = mKey*mAxisRect.data()->width();
7978 if (mParentAnchorX)
7978 if (mParentAnchorX)
7979 result.rx() += mParentAnchorX->pixelPoint().x();
7979 result.rx() += mParentAnchorX->pixelPoint().x();
7980 else
7980 else
7981 result.rx() += mAxisRect.data()->left();
7981 result.rx() += mAxisRect.data()->left();
7982 } else
7982 } else
7983 qDebug() << Q_FUNC_INFO << "Item position type x is ptAxisRectRatio, but no axis rect was defined";
7983 qDebug() << Q_FUNC_INFO << "Item position type x is ptAxisRectRatio, but no axis rect was defined";
7984 break;
7984 break;
7985 }
7985 }
7986 case ptPlotCoords:
7986 case ptPlotCoords:
7987 {
7987 {
7988 if (mKeyAxis && mKeyAxis.data()->orientation() == Qt::Horizontal)
7988 if (mKeyAxis && mKeyAxis.data()->orientation() == Qt::Horizontal)
7989 result.rx() = mKeyAxis.data()->coordToPixel(mKey);
7989 result.rx() = mKeyAxis.data()->coordToPixel(mKey);
7990 else if (mValueAxis && mValueAxis.data()->orientation() == Qt::Horizontal)
7990 else if (mValueAxis && mValueAxis.data()->orientation() == Qt::Horizontal)
7991 result.rx() = mValueAxis.data()->coordToPixel(mValue);
7991 result.rx() = mValueAxis.data()->coordToPixel(mValue);
7992 else
7992 else
7993 qDebug() << Q_FUNC_INFO << "Item position type x is ptPlotCoords, but no axes were defined";
7993 qDebug() << Q_FUNC_INFO << "Item position type x is ptPlotCoords, but no axes were defined";
7994 break;
7994 break;
7995 }
7995 }
7996 }
7996 }
7997
7997
7998 // determine Y:
7998 // determine Y:
7999 switch (mPositionTypeY)
7999 switch (mPositionTypeY)
8000 {
8000 {
8001 case ptAbsolute:
8001 case ptAbsolute:
8002 {
8002 {
8003 result.ry() = mValue;
8003 result.ry() = mValue;
8004 if (mParentAnchorY)
8004 if (mParentAnchorY)
8005 result.ry() += mParentAnchorY->pixelPoint().y();
8005 result.ry() += mParentAnchorY->pixelPoint().y();
8006 break;
8006 break;
8007 }
8007 }
8008 case ptViewportRatio:
8008 case ptViewportRatio:
8009 {
8009 {
8010 result.ry() = mValue*mParentPlot->viewport().height();
8010 result.ry() = mValue*mParentPlot->viewport().height();
8011 if (mParentAnchorY)
8011 if (mParentAnchorY)
8012 result.ry() += mParentAnchorY->pixelPoint().y();
8012 result.ry() += mParentAnchorY->pixelPoint().y();
8013 else
8013 else
8014 result.ry() += mParentPlot->viewport().top();
8014 result.ry() += mParentPlot->viewport().top();
8015 break;
8015 break;
8016 }
8016 }
8017 case ptAxisRectRatio:
8017 case ptAxisRectRatio:
8018 {
8018 {
8019 if (mAxisRect)
8019 if (mAxisRect)
8020 {
8020 {
8021 result.ry() = mValue*mAxisRect.data()->height();
8021 result.ry() = mValue*mAxisRect.data()->height();
8022 if (mParentAnchorY)
8022 if (mParentAnchorY)
8023 result.ry() += mParentAnchorY->pixelPoint().y();
8023 result.ry() += mParentAnchorY->pixelPoint().y();
8024 else
8024 else
8025 result.ry() += mAxisRect.data()->top();
8025 result.ry() += mAxisRect.data()->top();
8026 } else
8026 } else
8027 qDebug() << Q_FUNC_INFO << "Item position type y is ptAxisRectRatio, but no axis rect was defined";
8027 qDebug() << Q_FUNC_INFO << "Item position type y is ptAxisRectRatio, but no axis rect was defined";
8028 break;
8028 break;
8029 }
8029 }
8030 case ptPlotCoords:
8030 case ptPlotCoords:
8031 {
8031 {
8032 if (mKeyAxis && mKeyAxis.data()->orientation() == Qt::Vertical)
8032 if (mKeyAxis && mKeyAxis.data()->orientation() == Qt::Vertical)
8033 result.ry() = mKeyAxis.data()->coordToPixel(mKey);
8033 result.ry() = mKeyAxis.data()->coordToPixel(mKey);
8034 else if (mValueAxis && mValueAxis.data()->orientation() == Qt::Vertical)
8034 else if (mValueAxis && mValueAxis.data()->orientation() == Qt::Vertical)
8035 result.ry() = mValueAxis.data()->coordToPixel(mValue);
8035 result.ry() = mValueAxis.data()->coordToPixel(mValue);
8036 else
8036 else
8037 qDebug() << Q_FUNC_INFO << "Item position type y is ptPlotCoords, but no axes were defined";
8037 qDebug() << Q_FUNC_INFO << "Item position type y is ptPlotCoords, but no axes were defined";
8038 break;
8038 break;
8039 }
8039 }
8040 }
8040 }
8041
8041
8042 return result;
8042 return result;
8043 }
8043 }
8044
8044
8045 /*!
8045 /*!
@@ -8049,8 +8049,8 QPointF QCPItemPosition::pixelPoint() co
8049 */
8049 */
8050 void QCPItemPosition::setAxes(QCPAxis *keyAxis, QCPAxis *valueAxis)
8050 void QCPItemPosition::setAxes(QCPAxis *keyAxis, QCPAxis *valueAxis)
8051 {
8051 {
8052 mKeyAxis = keyAxis;
8052 mKeyAxis = keyAxis;
8053 mValueAxis = valueAxis;
8053 mValueAxis = valueAxis;
8054 }
8054 }
8055
8055
8056 /*!
8056 /*!
@@ -8060,7 +8060,7 void QCPItemPosition::setAxes(QCPAxis *k
8060 */
8060 */
8061 void QCPItemPosition::setAxisRect(QCPAxisRect *axisRect)
8061 void QCPItemPosition::setAxisRect(QCPAxisRect *axisRect)
8062 {
8062 {
8063 mAxisRect = axisRect;
8063 mAxisRect = axisRect;
8064 }
8064 }
8065
8065
8066 /*!
8066 /*!
@@ -8075,94 +8075,94 void QCPItemPosition::setAxisRect(QCPAxi
8075 */
8075 */
8076 void QCPItemPosition::setPixelPoint(const QPointF &pixelPoint)
8076 void QCPItemPosition::setPixelPoint(const QPointF &pixelPoint)
8077 {
8077 {
8078 double x = pixelPoint.x();
8078 double x = pixelPoint.x();
8079 double y = pixelPoint.y();
8079 double y = pixelPoint.y();
8080
8080
8081 switch (mPositionTypeX)
8081 switch (mPositionTypeX)
8082 {
8082 {
8083 case ptAbsolute:
8083 case ptAbsolute:
8084 {
8084 {
8085 if (mParentAnchorX)
8085 if (mParentAnchorX)
8086 x -= mParentAnchorX->pixelPoint().x();
8086 x -= mParentAnchorX->pixelPoint().x();
8087 break;
8087 break;
8088 }
8088 }
8089 case ptViewportRatio:
8089 case ptViewportRatio:
8090 {
8090 {
8091 if (mParentAnchorX)
8091 if (mParentAnchorX)
8092 x -= mParentAnchorX->pixelPoint().x();
8092 x -= mParentAnchorX->pixelPoint().x();
8093 else
8093 else
8094 x -= mParentPlot->viewport().left();
8094 x -= mParentPlot->viewport().left();
8095 x /= (double)mParentPlot->viewport().width();
8095 x /= (double)mParentPlot->viewport().width();
8096 break;
8096 break;
8097 }
8097 }
8098 case ptAxisRectRatio:
8098 case ptAxisRectRatio:
8099 {
8099 {
8100 if (mAxisRect)
8100 if (mAxisRect)
8101 {
8101 {
8102 if (mParentAnchorX)
8102 if (mParentAnchorX)
8103 x -= mParentAnchorX->pixelPoint().x();
8103 x -= mParentAnchorX->pixelPoint().x();
8104 else
8104 else
8105 x -= mAxisRect.data()->left();
8105 x -= mAxisRect.data()->left();
8106 x /= (double)mAxisRect.data()->width();
8106 x /= (double)mAxisRect.data()->width();
8107 } else
8107 } else
8108 qDebug() << Q_FUNC_INFO << "Item position type x is ptAxisRectRatio, but no axis rect was defined";
8108 qDebug() << Q_FUNC_INFO << "Item position type x is ptAxisRectRatio, but no axis rect was defined";
8109 break;
8109 break;
8110 }
8110 }
8111 case ptPlotCoords:
8111 case ptPlotCoords:
8112 {
8112 {
8113 if (mKeyAxis && mKeyAxis.data()->orientation() == Qt::Horizontal)
8113 if (mKeyAxis && mKeyAxis.data()->orientation() == Qt::Horizontal)
8114 x = mKeyAxis.data()->pixelToCoord(x);
8114 x = mKeyAxis.data()->pixelToCoord(x);
8115 else if (mValueAxis && mValueAxis.data()->orientation() == Qt::Horizontal)
8115 else if (mValueAxis && mValueAxis.data()->orientation() == Qt::Horizontal)
8116 y = mValueAxis.data()->pixelToCoord(x);
8116 y = mValueAxis.data()->pixelToCoord(x);
8117 else
8117 else
8118 qDebug() << Q_FUNC_INFO << "Item position type x is ptPlotCoords, but no axes were defined";
8118 qDebug() << Q_FUNC_INFO << "Item position type x is ptPlotCoords, but no axes were defined";
8119 break;
8119 break;
8120 }
8120 }
8121 }
8121 }
8122
8122
8123 switch (mPositionTypeY)
8123 switch (mPositionTypeY)
8124 {
8124 {
8125 case ptAbsolute:
8125 case ptAbsolute:
8126 {
8126 {
8127 if (mParentAnchorY)
8127 if (mParentAnchorY)
8128 y -= mParentAnchorY->pixelPoint().y();
8128 y -= mParentAnchorY->pixelPoint().y();
8129 break;
8129 break;
8130 }
8130 }
8131 case ptViewportRatio:
8131 case ptViewportRatio:
8132 {
8132 {
8133 if (mParentAnchorY)
8133 if (mParentAnchorY)
8134 y -= mParentAnchorY->pixelPoint().y();
8134 y -= mParentAnchorY->pixelPoint().y();
8135 else
8135 else
8136 y -= mParentPlot->viewport().top();
8136 y -= mParentPlot->viewport().top();
8137 y /= (double)mParentPlot->viewport().height();
8137 y /= (double)mParentPlot->viewport().height();
8138 break;
8138 break;
8139 }
8139 }
8140 case ptAxisRectRatio:
8140 case ptAxisRectRatio:
8141 {
8141 {
8142 if (mAxisRect)
8142 if (mAxisRect)
8143 {
8143 {
8144 if (mParentAnchorY)
8144 if (mParentAnchorY)
8145 y -= mParentAnchorY->pixelPoint().y();
8145 y -= mParentAnchorY->pixelPoint().y();
8146 else
8146 else
8147 y -= mAxisRect.data()->top();
8147 y -= mAxisRect.data()->top();
8148 y /= (double)mAxisRect.data()->height();
8148 y /= (double)mAxisRect.data()->height();
8149 } else
8149 } else
8150 qDebug() << Q_FUNC_INFO << "Item position type y is ptAxisRectRatio, but no axis rect was defined";
8150 qDebug() << Q_FUNC_INFO << "Item position type y is ptAxisRectRatio, but no axis rect was defined";
8151 break;
8151 break;
8152 }
8152 }
8153 case ptPlotCoords:
8153 case ptPlotCoords:
8154 {
8154 {
8155 if (mKeyAxis && mKeyAxis.data()->orientation() == Qt::Vertical)
8155 if (mKeyAxis && mKeyAxis.data()->orientation() == Qt::Vertical)
8156 x = mKeyAxis.data()->pixelToCoord(y);
8156 x = mKeyAxis.data()->pixelToCoord(y);
8157 else if (mValueAxis && mValueAxis.data()->orientation() == Qt::Vertical)
8157 else if (mValueAxis && mValueAxis.data()->orientation() == Qt::Vertical)
8158 y = mValueAxis.data()->pixelToCoord(y);
8158 y = mValueAxis.data()->pixelToCoord(y);
8159 else
8159 else
8160 qDebug() << Q_FUNC_INFO << "Item position type y is ptPlotCoords, but no axes were defined";
8160 qDebug() << Q_FUNC_INFO << "Item position type y is ptPlotCoords, but no axes were defined";
8161 break;
8161 break;
8162 }
8162 }
8163 }
8163 }
8164
8164
8165 setCoords(x, y);
8165 setCoords(x, y);
8166 }
8166 }
8167
8167
8168
8168
@@ -8353,29 +8353,29 void QCPItemPosition::setPixelPoint(cons
8353 Base class constructor which initializes base class members.
8353 Base class constructor which initializes base class members.
8354 */
8354 */
8355 QCPAbstractItem::QCPAbstractItem(QCustomPlot *parentPlot) :
8355 QCPAbstractItem::QCPAbstractItem(QCustomPlot *parentPlot) :
8356 QCPLayerable(parentPlot),
8356 QCPLayerable(parentPlot),
8357 mClipToAxisRect(false),
8357 mClipToAxisRect(false),
8358 mSelectable(true),
8358 mSelectable(true),
8359 mSelected(false)
8359 mSelected(false)
8360 {
8360 {
8361 QList<QCPAxisRect*> rects = parentPlot->axisRects();
8361 QList<QCPAxisRect*> rects = parentPlot->axisRects();
8362 if (rects.size() > 0)
8362 if (rects.size() > 0)
8363 {
8363 {
8364 setClipToAxisRect(true);
8364 setClipToAxisRect(true);
8365 setClipAxisRect(rects.first());
8365 setClipAxisRect(rects.first());
8366 }
8366 }
8367 }
8367 }
8368
8368
8369 QCPAbstractItem::~QCPAbstractItem()
8369 QCPAbstractItem::~QCPAbstractItem()
8370 {
8370 {
8371 // don't delete mPositions because every position is also an anchor and thus in mAnchors
8371 // don't delete mPositions because every position is also an anchor and thus in mAnchors
8372 qDeleteAll(mAnchors);
8372 qDeleteAll(mAnchors);
8373 }
8373 }
8374
8374
8375 /* can't make this a header inline function, because QPointer breaks with forward declared types, see QTBUG-29588 */
8375 /* can't make this a header inline function, because QPointer breaks with forward declared types, see QTBUG-29588 */
8376 QCPAxisRect *QCPAbstractItem::clipAxisRect() const
8376 QCPAxisRect *QCPAbstractItem::clipAxisRect() const
8377 {
8377 {
8378 return mClipAxisRect.data();
8378 return mClipAxisRect.data();
8379 }
8379 }
8380
8380
8381 /*!
8381 /*!
@@ -8386,9 +8386,9 QCPAxisRect *QCPAbstractItem::clipAxisRe
8386 */
8386 */
8387 void QCPAbstractItem::setClipToAxisRect(bool clip)
8387 void QCPAbstractItem::setClipToAxisRect(bool clip)
8388 {
8388 {
8389 mClipToAxisRect = clip;
8389 mClipToAxisRect = clip;
8390 if (mClipToAxisRect)
8390 if (mClipToAxisRect)
8391 setParentLayerable(mClipAxisRect.data());
8391 setParentLayerable(mClipAxisRect.data());
8392 }
8392 }
8393
8393
8394 /*!
8394 /*!
@@ -8399,9 +8399,9 void QCPAbstractItem::setClipToAxisRect(
8399 */
8399 */
8400 void QCPAbstractItem::setClipAxisRect(QCPAxisRect *rect)
8400 void QCPAbstractItem::setClipAxisRect(QCPAxisRect *rect)
8401 {
8401 {
8402 mClipAxisRect = rect;
8402 mClipAxisRect = rect;
8403 if (mClipToAxisRect)
8403 if (mClipToAxisRect)
8404 setParentLayerable(mClipAxisRect.data());
8404 setParentLayerable(mClipAxisRect.data());
8405 }
8405 }
8406
8406
8407 /*!
8407 /*!
@@ -8415,10 +8415,10 void QCPAbstractItem::setClipAxisRect(QC
8415 */
8415 */
8416 void QCPAbstractItem::setSelectable(bool selectable)
8416 void QCPAbstractItem::setSelectable(bool selectable)
8417 {
8417 {
8418 if (mSelectable != selectable)
8418 if (mSelectable != selectable)
8419 {
8419 {
8420 mSelectable = selectable;
8420 mSelectable = selectable;
8421 emit selectableChanged(mSelectable);
8421 emit selectableChanged(mSelectable);
8422 }
8422 }
8423 }
8423 }
8424
8424
@@ -8438,10 +8438,10 void QCPAbstractItem::setSelectable(bool
8438 */
8438 */
8439 void QCPAbstractItem::setSelected(bool selected)
8439 void QCPAbstractItem::setSelected(bool selected)
8440 {
8440 {
8441 if (mSelected != selected)
8441 if (mSelected != selected)
8442 {
8442 {
8443 mSelected = selected;
8443 mSelected = selected;
8444 emit selectionChanged(mSelected);
8444 emit selectionChanged(mSelected);
8445 }
8445 }
8446 }
8446 }
8447
8447
@@ -8457,13 +8457,13 void QCPAbstractItem::setSelected(bool s
8457 */
8457 */
8458 QCPItemPosition *QCPAbstractItem::position(const QString &name) const
8458 QCPItemPosition *QCPAbstractItem::position(const QString &name) const
8459 {
8459 {
8460 for (int i=0; i<mPositions.size(); ++i)
8460 for (int i=0; i<mPositions.size(); ++i)
8461 {
8461 {
8462 if (mPositions.at(i)->name() == name)
8462 if (mPositions.at(i)->name() == name)
8463 return mPositions.at(i);
8463 return mPositions.at(i);
8464 }
8464 }
8465 qDebug() << Q_FUNC_INFO << "position with name not found:" << name;
8465 qDebug() << Q_FUNC_INFO << "position with name not found:" << name;
8466 return 0;
8466 return 0;
8467 }
8467 }
8468
8468
8469 /*!
8469 /*!
@@ -8478,13 +8478,13 QCPItemPosition *QCPAbstractItem::positi
8478 */
8478 */
8479 QCPItemAnchor *QCPAbstractItem::anchor(const QString &name) const
8479 QCPItemAnchor *QCPAbstractItem::anchor(const QString &name) const
8480 {
8480 {
8481 for (int i=0; i<mAnchors.size(); ++i)
8481 for (int i=0; i<mAnchors.size(); ++i)
8482 {
8482 {
8483 if (mAnchors.at(i)->name() == name)
8483 if (mAnchors.at(i)->name() == name)
8484 return mAnchors.at(i);
8484 return mAnchors.at(i);
8485 }
8485 }
8486 qDebug() << Q_FUNC_INFO << "anchor with name not found:" << name;
8486 qDebug() << Q_FUNC_INFO << "anchor with name not found:" << name;
8487 return 0;
8487 return 0;
8488 }
8488 }
8489
8489
8490 /*!
8490 /*!
@@ -8497,12 +8497,12 QCPItemAnchor *QCPAbstractItem::anchor(c
8497 */
8497 */
8498 bool QCPAbstractItem::hasAnchor(const QString &name) const
8498 bool QCPAbstractItem::hasAnchor(const QString &name) const
8499 {
8499 {
8500 for (int i=0; i<mAnchors.size(); ++i)
8500 for (int i=0; i<mAnchors.size(); ++i)
8501 {
8501 {
8502 if (mAnchors.at(i)->name() == name)
8502 if (mAnchors.at(i)->name() == name)
8503 return true;
8503 return true;
8504 }
8504 }
8505 return false;
8505 return false;
8506 }
8506 }
8507
8507
8508 /*! \internal
8508 /*! \internal
@@ -8516,10 +8516,10 bool QCPAbstractItem::hasAnchor(const QS
8516 */
8516 */
8517 QRect QCPAbstractItem::clipRect() const
8517 QRect QCPAbstractItem::clipRect() const
8518 {
8518 {
8519 if (mClipToAxisRect && mClipAxisRect)
8519 if (mClipToAxisRect && mClipAxisRect)
8520 return mClipAxisRect.data()->rect();
8520 return mClipAxisRect.data()->rect();
8521 else
8521 else
8522 return mParentPlot->viewport();
8522 return mParentPlot->viewport();
8523 }
8523 }
8524
8524
8525 /*! \internal
8525 /*! \internal
@@ -8537,7 +8537,7 QRect QCPAbstractItem::clipRect() const
8537 */
8537 */
8538 void QCPAbstractItem::applyDefaultAntialiasingHint(QCPPainter *painter) const
8538 void QCPAbstractItem::applyDefaultAntialiasingHint(QCPPainter *painter) const
8539 {
8539 {
8540 applyAntialiasingHint(painter, mAntialiased, QCP::aeItems);
8540 applyAntialiasingHint(painter, mAntialiased, QCP::aeItems);
8541 }
8541 }
8542
8542
8543 /*! \internal
8543 /*! \internal
@@ -8554,23 +8554,23 void QCPAbstractItem::applyDefaultAntial
8554 */
8554 */
8555 double QCPAbstractItem::distSqrToLine(const QPointF &start, const QPointF &end, const QPointF &point) const
8555 double QCPAbstractItem::distSqrToLine(const QPointF &start, const QPointF &end, const QPointF &point) const
8556 {
8556 {
8557 QVector2D a(start);
8557 QVector2D a(start);
8558 QVector2D b(end);
8558 QVector2D b(end);
8559 QVector2D p(point);
8559 QVector2D p(point);
8560 QVector2D v(b-a);
8560 QVector2D v(b-a);
8561
8561
8562 double vLengthSqr = v.lengthSquared();
8562 double vLengthSqr = v.lengthSquared();
8563 if (!qFuzzyIsNull(vLengthSqr))
8563 if (!qFuzzyIsNull(vLengthSqr))
8564 {
8564 {
8565 double mu = QVector2D::dotProduct(p-a, v)/vLengthSqr;
8565 double mu = QVector2D::dotProduct(p-a, v)/vLengthSqr;
8566 if (mu < 0)
8566 if (mu < 0)
8567 return (a-p).lengthSquared();
8568 else if (mu > 1)
8569 return (b-p).lengthSquared();
8570 else
8571 return ((a + mu*v)-p).lengthSquared();
8572 } else
8567 return (a-p).lengthSquared();
8573 return (a-p).lengthSquared();
8568 else if (mu > 1)
8569 return (b-p).lengthSquared();
8570 else
8571 return ((a + mu*v)-p).lengthSquared();
8572 } else
8573 return (a-p).lengthSquared();
8574 }
8574 }
8575
8575
8576 /*! \internal
8576 /*! \internal
@@ -8592,28 +8592,28 double QCPAbstractItem::distSqrToLine(co
8592 */
8592 */
8593 double QCPAbstractItem::rectSelectTest(const QRectF &rect, const QPointF &pos, bool filledRect) const
8593 double QCPAbstractItem::rectSelectTest(const QRectF &rect, const QPointF &pos, bool filledRect) const
8594 {
8594 {
8595 double result = -1;
8595 double result = -1;
8596
8596
8597 // distance to border:
8597 // distance to border:
8598 QList<QLineF> lines;
8598 QList<QLineF> lines;
8599 lines << QLineF(rect.topLeft(), rect.topRight()) << QLineF(rect.bottomLeft(), rect.bottomRight())
8599 lines << QLineF(rect.topLeft(), rect.topRight()) << QLineF(rect.bottomLeft(), rect.bottomRight())
8600 << QLineF(rect.topLeft(), rect.bottomLeft()) << QLineF(rect.topRight(), rect.bottomRight());
8600 << QLineF(rect.topLeft(), rect.bottomLeft()) << QLineF(rect.topRight(), rect.bottomRight());
8601 double minDistSqr = std::numeric_limits<double>::max();
8601 double minDistSqr = std::numeric_limits<double>::max();
8602 for (int i=0; i<lines.size(); ++i)
8602 for (int i=0; i<lines.size(); ++i)
8603 {
8603 {
8604 double distSqr = distSqrToLine(lines.at(i).p1(), lines.at(i).p2(), pos);
8604 double distSqr = distSqrToLine(lines.at(i).p1(), lines.at(i).p2(), pos);
8605 if (distSqr < minDistSqr)
8605 if (distSqr < minDistSqr)
8606 minDistSqr = distSqr;
8606 minDistSqr = distSqr;
8607 }
8607 }
8608 result = qSqrt(minDistSqr);
8608 result = qSqrt(minDistSqr);
8609
8609
8610 // filled rect, allow click inside to count as hit:
8610 // filled rect, allow click inside to count as hit:
8611 if (filledRect && result > mParentPlot->selectionTolerance()*0.99)
8611 if (filledRect && result > mParentPlot->selectionTolerance()*0.99)
8612 {
8612 {
8613 if (rect.contains(pos))
8613 if (rect.contains(pos))
8614 result = mParentPlot->selectionTolerance()*0.99;
8614 result = mParentPlot->selectionTolerance()*0.99;
8615 }
8615 }
8616 return result;
8616 return result;
8617 }
8617 }
8618
8618
8619 /*! \internal
8619 /*! \internal
@@ -8628,8 +8628,8 double QCPAbstractItem::rectSelectTest(c
8628 */
8628 */
8629 QPointF QCPAbstractItem::anchorPixelPoint(int anchorId) const
8629 QPointF QCPAbstractItem::anchorPixelPoint(int anchorId) const
8630 {
8630 {
8631 qDebug() << Q_FUNC_INFO << "called on item which shouldn't have any anchors (this method not reimplemented). anchorId" << anchorId;
8631 qDebug() << Q_FUNC_INFO << "called on item which shouldn't have any anchors (this method not reimplemented). anchorId" << anchorId;
8632 return QPointF();
8632 return QPointF();
8633 }
8633 }
8634
8634
8635 /*! \internal
8635 /*! \internal
@@ -8648,17 +8648,17 QPointF QCPAbstractItem::anchorPixelPoin
8648 */
8648 */
8649 QCPItemPosition *QCPAbstractItem::createPosition(const QString &name)
8649 QCPItemPosition *QCPAbstractItem::createPosition(const QString &name)
8650 {
8650 {
8651 if (hasAnchor(name))
8651 if (hasAnchor(name))
8652 qDebug() << Q_FUNC_INFO << "anchor/position with name exists already:" << name;
8652 qDebug() << Q_FUNC_INFO << "anchor/position with name exists already:" << name;
8653 QCPItemPosition *newPosition = new QCPItemPosition(mParentPlot, this, name);
8653 QCPItemPosition *newPosition = new QCPItemPosition(mParentPlot, this, name);
8654 mPositions.append(newPosition);
8654 mPositions.append(newPosition);
8655 mAnchors.append(newPosition); // every position is also an anchor
8655 mAnchors.append(newPosition); // every position is also an anchor
8656 newPosition->setAxes(mParentPlot->xAxis, mParentPlot->yAxis);
8656 newPosition->setAxes(mParentPlot->xAxis, mParentPlot->yAxis);
8657 newPosition->setType(QCPItemPosition::ptPlotCoords);
8657 newPosition->setType(QCPItemPosition::ptPlotCoords);
8658 if (mParentPlot->axisRect())
8658 if (mParentPlot->axisRect())
8659 newPosition->setAxisRect(mParentPlot->axisRect());
8659 newPosition->setAxisRect(mParentPlot->axisRect());
8660 newPosition->setCoords(0, 0);
8660 newPosition->setCoords(0, 0);
8661 return newPosition;
8661 return newPosition;
8662 }
8662 }
8663
8663
8664 /*! \internal
8664 /*! \internal
@@ -8682,43 +8682,43 QCPItemPosition *QCPAbstractItem::create
8682 */
8682 */
8683 QCPItemAnchor *QCPAbstractItem::createAnchor(const QString &name, int anchorId)
8683 QCPItemAnchor *QCPAbstractItem::createAnchor(const QString &name, int anchorId)
8684 {
8684 {
8685 if (hasAnchor(name))
8685 if (hasAnchor(name))
8686 qDebug() << Q_FUNC_INFO << "anchor/position with name exists already:" << name;
8686 qDebug() << Q_FUNC_INFO << "anchor/position with name exists already:" << name;
8687 QCPItemAnchor *newAnchor = new QCPItemAnchor(mParentPlot, this, name, anchorId);
8687 QCPItemAnchor *newAnchor = new QCPItemAnchor(mParentPlot, this, name, anchorId);
8688 mAnchors.append(newAnchor);
8688 mAnchors.append(newAnchor);
8689 return newAnchor;
8689 return newAnchor;
8690 }
8690 }
8691
8691
8692 /* inherits documentation from base class */
8692 /* inherits documentation from base class */
8693 void QCPAbstractItem::selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged)
8693 void QCPAbstractItem::selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged)
8694 {
8694 {
8695 Q_UNUSED(event)
8695 Q_UNUSED(event)
8696 Q_UNUSED(details)
8696 Q_UNUSED(details)
8697 if (mSelectable)
8697 if (mSelectable)
8698 {
8698 {
8699 bool selBefore = mSelected;
8699 bool selBefore = mSelected;
8700 setSelected(additive ? !mSelected : true);
8700 setSelected(additive ? !mSelected : true);
8701 if (selectionStateChanged)
8701 if (selectionStateChanged)
8702 *selectionStateChanged = mSelected != selBefore;
8702 *selectionStateChanged = mSelected != selBefore;
8703 }
8703 }
8704 }
8704 }
8705
8705
8706 /* inherits documentation from base class */
8706 /* inherits documentation from base class */
8707 void QCPAbstractItem::deselectEvent(bool *selectionStateChanged)
8707 void QCPAbstractItem::deselectEvent(bool *selectionStateChanged)
8708 {
8708 {
8709 if (mSelectable)
8709 if (mSelectable)
8710 {
8710 {
8711 bool selBefore = mSelected;
8711 bool selBefore = mSelected;
8712 setSelected(false);
8712 setSelected(false);
8713 if (selectionStateChanged)
8713 if (selectionStateChanged)
8714 *selectionStateChanged = mSelected != selBefore;
8714 *selectionStateChanged = mSelected != selBefore;
8715 }
8715 }
8716 }
8716 }
8717
8717
8718 /* inherits documentation from base class */
8718 /* inherits documentation from base class */
8719 QCP::Interaction QCPAbstractItem::selectionCategory() const
8719 QCP::Interaction QCPAbstractItem::selectionCategory() const
8720 {
8720 {
8721 return QCP::iSelectItems;
8721 return QCP::iSelectItems;
8722 }
8722 }
8723
8723
8724
8724
@@ -9032,91 +9032,91 QCP::Interaction QCPAbstractItem::select
9032 Constructs a QCustomPlot and sets reasonable default values.
9032 Constructs a QCustomPlot and sets reasonable default values.
9033 */
9033 */
9034 QCustomPlot::QCustomPlot(QWidget *parent) :
9034 QCustomPlot::QCustomPlot(QWidget *parent) :
9035 QWidget(parent),
9035 QWidget(parent),
9036 xAxis(0),
9036 xAxis(0),
9037 yAxis(0),
9037 yAxis(0),
9038 xAxis2(0),
9038 xAxis2(0),
9039 yAxis2(0),
9039 yAxis2(0),
9040 legend(0),
9040 legend(0),
9041 mPlotLayout(0),
9041 mPlotLayout(0),
9042 mAutoAddPlottableToLegend(true),
9042 mAutoAddPlottableToLegend(true),
9043 mAntialiasedElements(QCP::aeNone),
9043 mAntialiasedElements(QCP::aeNone),
9044 mNotAntialiasedElements(QCP::aeNone),
9044 mNotAntialiasedElements(QCP::aeNone),
9045 mInteractions(0),
9045 mInteractions(0),
9046 mSelectionTolerance(8),
9046 mSelectionTolerance(8),
9047 mNoAntialiasingOnDrag(false),
9047 mNoAntialiasingOnDrag(false),
9048 mBackgroundBrush(Qt::white, Qt::SolidPattern),
9048 mBackgroundBrush(Qt::white, Qt::SolidPattern),
9049 mBackgroundScaled(true),
9049 mBackgroundScaled(true),
9050 mBackgroundScaledMode(Qt::KeepAspectRatioByExpanding),
9050 mBackgroundScaledMode(Qt::KeepAspectRatioByExpanding),
9051 mCurrentLayer(0),
9051 mCurrentLayer(0),
9052 mPlottingHints(QCP::phCacheLabels|QCP::phForceRepaint),
9052 mPlottingHints(QCP::phCacheLabels|QCP::phForceRepaint),
9053 mMultiSelectModifier(Qt::ControlModifier),
9053 mMultiSelectModifier(Qt::ControlModifier),
9054 mPaintBuffer(size()),
9054 mPaintBuffer(size()),
9055 mMouseEventElement(0),
9055 mMouseEventElement(0),
9056 mReplotting(false)
9056 mReplotting(false)
9057 {
9057 {
9058 setAttribute(Qt::WA_NoMousePropagation);
9058 setAttribute(Qt::WA_NoMousePropagation);
9059 setAttribute(Qt::WA_OpaquePaintEvent);
9059 setAttribute(Qt::WA_OpaquePaintEvent);
9060 setMouseTracking(true);
9060 setMouseTracking(true);
9061 QLocale currentLocale = locale();
9061 QLocale currentLocale = locale();
9062 currentLocale.setNumberOptions(QLocale::OmitGroupSeparator);
9062 currentLocale.setNumberOptions(QLocale::OmitGroupSeparator);
9063 setLocale(currentLocale);
9063 setLocale(currentLocale);
9064
9064
9065 // create initial layers:
9065 // create initial layers:
9066 mLayers.append(new QCPLayer(this, QLatin1String("background")));
9066 mLayers.append(new QCPLayer(this, QLatin1String("background")));
9067 mLayers.append(new QCPLayer(this, QLatin1String("grid")));
9067 mLayers.append(new QCPLayer(this, QLatin1String("grid")));
9068 mLayers.append(new QCPLayer(this, QLatin1String("main")));
9068 mLayers.append(new QCPLayer(this, QLatin1String("main")));
9069 mLayers.append(new QCPLayer(this, QLatin1String("axes")));
9069 mLayers.append(new QCPLayer(this, QLatin1String("axes")));
9070 mLayers.append(new QCPLayer(this, QLatin1String("legend")));
9070 mLayers.append(new QCPLayer(this, QLatin1String("legend")));
9071 updateLayerIndices();
9071 updateLayerIndices();
9072 setCurrentLayer(QLatin1String("main"));
9072 setCurrentLayer(QLatin1String("main"));
9073
9073
9074 // create initial layout, axis rect and legend:
9074 // create initial layout, axis rect and legend:
9075 mPlotLayout = new QCPLayoutGrid;
9075 mPlotLayout = new QCPLayoutGrid;
9076 mPlotLayout->initializeParentPlot(this);
9076 mPlotLayout->initializeParentPlot(this);
9077 mPlotLayout->setParent(this); // important because if parent is QWidget, QCPLayout::sizeConstraintsChanged will call QWidget::updateGeometry
9077 mPlotLayout->setParent(this); // important because if parent is QWidget, QCPLayout::sizeConstraintsChanged will call QWidget::updateGeometry
9078 mPlotLayout->setLayer(QLatin1String("main"));
9078 mPlotLayout->setLayer(QLatin1String("main"));
9079 QCPAxisRect *defaultAxisRect = new QCPAxisRect(this, true);
9079 QCPAxisRect *defaultAxisRect = new QCPAxisRect(this, true);
9080 mPlotLayout->addElement(0, 0, defaultAxisRect);
9080 mPlotLayout->addElement(0, 0, defaultAxisRect);
9081 xAxis = defaultAxisRect->axis(QCPAxis::atBottom);
9081 xAxis = defaultAxisRect->axis(QCPAxis::atBottom);
9082 yAxis = defaultAxisRect->axis(QCPAxis::atLeft);
9082 yAxis = defaultAxisRect->axis(QCPAxis::atLeft);
9083 xAxis2 = defaultAxisRect->axis(QCPAxis::atTop);
9083 xAxis2 = defaultAxisRect->axis(QCPAxis::atTop);
9084 yAxis2 = defaultAxisRect->axis(QCPAxis::atRight);
9084 yAxis2 = defaultAxisRect->axis(QCPAxis::atRight);
9085 legend = new QCPLegend;
9085 legend = new QCPLegend;
9086 legend->setVisible(false);
9086 legend->setVisible(false);
9087 defaultAxisRect->insetLayout()->addElement(legend, Qt::AlignRight|Qt::AlignTop);
9087 defaultAxisRect->insetLayout()->addElement(legend, Qt::AlignRight|Qt::AlignTop);
9088 defaultAxisRect->insetLayout()->setMargins(QMargins(12, 12, 12, 12));
9088 defaultAxisRect->insetLayout()->setMargins(QMargins(12, 12, 12, 12));
9089
9089
9090 defaultAxisRect->setLayer(QLatin1String("background"));
9090 defaultAxisRect->setLayer(QLatin1String("background"));
9091 xAxis->setLayer(QLatin1String("axes"));
9091 xAxis->setLayer(QLatin1String("axes"));
9092 yAxis->setLayer(QLatin1String("axes"));
9092 yAxis->setLayer(QLatin1String("axes"));
9093 xAxis2->setLayer(QLatin1String("axes"));
9093 xAxis2->setLayer(QLatin1String("axes"));
9094 yAxis2->setLayer(QLatin1String("axes"));
9094 yAxis2->setLayer(QLatin1String("axes"));
9095 xAxis->grid()->setLayer(QLatin1String("grid"));
9095 xAxis->grid()->setLayer(QLatin1String("grid"));
9096 yAxis->grid()->setLayer(QLatin1String("grid"));
9096 yAxis->grid()->setLayer(QLatin1String("grid"));
9097 xAxis2->grid()->setLayer(QLatin1String("grid"));
9097 xAxis2->grid()->setLayer(QLatin1String("grid"));
9098 yAxis2->grid()->setLayer(QLatin1String("grid"));
9098 yAxis2->grid()->setLayer(QLatin1String("grid"));
9099 legend->setLayer(QLatin1String("legend"));
9099 legend->setLayer(QLatin1String("legend"));
9100
9100
9101 setViewport(rect()); // needs to be called after mPlotLayout has been created
9101 setViewport(rect()); // needs to be called after mPlotLayout has been created
9102
9102
9103 replot();
9103 replot();
9104 }
9104 }
9105
9105
9106 QCustomPlot::~QCustomPlot()
9106 QCustomPlot::~QCustomPlot()
9107 {
9107 {
9108 clearPlottables();
9108 clearPlottables();
9109 clearItems();
9109 clearItems();
9110
9110
9111 if (mPlotLayout)
9111 if (mPlotLayout)
9112 {
9112 {
9113 delete mPlotLayout;
9113 delete mPlotLayout;
9114 mPlotLayout = 0;
9114 mPlotLayout = 0;
9115 }
9115 }
9116
9116
9117 mCurrentLayer = 0;
9117 mCurrentLayer = 0;
9118 qDeleteAll(mLayers); // don't use removeLayer, because it would prevent the last layer to be removed
9118 qDeleteAll(mLayers); // don't use removeLayer, because it would prevent the last layer to be removed
9119 mLayers.clear();
9119 mLayers.clear();
9120 }
9120 }
9121
9121
9122 /*!
9122 /*!
@@ -9138,11 +9138,11 QCustomPlot::~QCustomPlot()
9138 */
9138 */
9139 void QCustomPlot::setAntialiasedElements(const QCP::AntialiasedElements &antialiasedElements)
9139 void QCustomPlot::setAntialiasedElements(const QCP::AntialiasedElements &antialiasedElements)
9140 {
9140 {
9141 mAntialiasedElements = antialiasedElements;
9141 mAntialiasedElements = antialiasedElements;
9142
9142
9143 // make sure elements aren't in mNotAntialiasedElements and mAntialiasedElements simultaneously:
9143 // make sure elements aren't in mNotAntialiasedElements and mAntialiasedElements simultaneously:
9144 if ((mNotAntialiasedElements & mAntialiasedElements) != 0)
9144 if ((mNotAntialiasedElements & mAntialiasedElements) != 0)
9145 mNotAntialiasedElements |= ~mAntialiasedElements;
9145 mNotAntialiasedElements |= ~mAntialiasedElements;
9146 }
9146 }
9147
9147
9148 /*!
9148 /*!
@@ -9154,14 +9154,14 void QCustomPlot::setAntialiasedElements
9154 */
9154 */
9155 void QCustomPlot::setAntialiasedElement(QCP::AntialiasedElement antialiasedElement, bool enabled)
9155 void QCustomPlot::setAntialiasedElement(QCP::AntialiasedElement antialiasedElement, bool enabled)
9156 {
9156 {
9157 if (!enabled && mAntialiasedElements.testFlag(antialiasedElement))
9157 if (!enabled && mAntialiasedElements.testFlag(antialiasedElement))
9158 mAntialiasedElements &= ~antialiasedElement;
9158 mAntialiasedElements &= ~antialiasedElement;
9159 else if (enabled && !mAntialiasedElements.testFlag(antialiasedElement))
9159 else if (enabled && !mAntialiasedElements.testFlag(antialiasedElement))
9160 mAntialiasedElements |= antialiasedElement;
9160 mAntialiasedElements |= antialiasedElement;
9161
9161
9162 // make sure elements aren't in mNotAntialiasedElements and mAntialiasedElements simultaneously:
9162 // make sure elements aren't in mNotAntialiasedElements and mAntialiasedElements simultaneously:
9163 if ((mNotAntialiasedElements & mAntialiasedElements) != 0)
9163 if ((mNotAntialiasedElements & mAntialiasedElements) != 0)
9164 mNotAntialiasedElements |= ~mAntialiasedElements;
9164 mNotAntialiasedElements |= ~mAntialiasedElements;
9165 }
9165 }
9166
9166
9167 /*!
9167 /*!
@@ -9184,11 +9184,11 void QCustomPlot::setAntialiasedElement(
9184 */
9184 */
9185 void QCustomPlot::setNotAntialiasedElements(const QCP::AntialiasedElements &notAntialiasedElements)
9185 void QCustomPlot::setNotAntialiasedElements(const QCP::AntialiasedElements &notAntialiasedElements)
9186 {
9186 {
9187 mNotAntialiasedElements = notAntialiasedElements;
9187 mNotAntialiasedElements = notAntialiasedElements;
9188
9188
9189 // make sure elements aren't in mNotAntialiasedElements and mAntialiasedElements simultaneously:
9189 // make sure elements aren't in mNotAntialiasedElements and mAntialiasedElements simultaneously:
9190 if ((mNotAntialiasedElements & mAntialiasedElements) != 0)
9190 if ((mNotAntialiasedElements & mAntialiasedElements) != 0)
9191 mAntialiasedElements |= ~mNotAntialiasedElements;
9191 mAntialiasedElements |= ~mNotAntialiasedElements;
9192 }
9192 }
9193
9193
9194 /*!
9194 /*!
@@ -9200,14 +9200,14 void QCustomPlot::setNotAntialiasedEleme
9200 */
9200 */
9201 void QCustomPlot::setNotAntialiasedElement(QCP::AntialiasedElement notAntialiasedElement, bool enabled)
9201 void QCustomPlot::setNotAntialiasedElement(QCP::AntialiasedElement notAntialiasedElement, bool enabled)
9202 {
9202 {
9203 if (!enabled && mNotAntialiasedElements.testFlag(notAntialiasedElement))
9203 if (!enabled && mNotAntialiasedElements.testFlag(notAntialiasedElement))
9204 mNotAntialiasedElements &= ~notAntialiasedElement;
9204 mNotAntialiasedElements &= ~notAntialiasedElement;
9205 else if (enabled && !mNotAntialiasedElements.testFlag(notAntialiasedElement))
9205 else if (enabled && !mNotAntialiasedElements.testFlag(notAntialiasedElement))
9206 mNotAntialiasedElements |= notAntialiasedElement;
9206 mNotAntialiasedElements |= notAntialiasedElement;
9207
9207
9208 // make sure elements aren't in mNotAntialiasedElements and mAntialiasedElements simultaneously:
9208 // make sure elements aren't in mNotAntialiasedElements and mAntialiasedElements simultaneously:
9209 if ((mNotAntialiasedElements & mAntialiasedElements) != 0)
9209 if ((mNotAntialiasedElements & mAntialiasedElements) != 0)
9210 mAntialiasedElements |= ~mNotAntialiasedElements;
9210 mAntialiasedElements |= ~mNotAntialiasedElements;
9211 }
9211 }
9212
9212
9213 /*!
9213 /*!
@@ -9218,7 +9218,7 void QCustomPlot::setNotAntialiasedEleme
9218 */
9218 */
9219 void QCustomPlot::setAutoAddPlottableToLegend(bool on)
9219 void QCustomPlot::setAutoAddPlottableToLegend(bool on)
9220 {
9220 {
9221 mAutoAddPlottableToLegend = on;
9221 mAutoAddPlottableToLegend = on;
9222 }
9222 }
9223
9223
9224 /*!
9224 /*!
@@ -9277,7 +9277,7 void QCustomPlot::setAutoAddPlottableToL
9277 */
9277 */
9278 void QCustomPlot::setInteractions(const QCP::Interactions &interactions)
9278 void QCustomPlot::setInteractions(const QCP::Interactions &interactions)
9279 {
9279 {
9280 mInteractions = interactions;
9280 mInteractions = interactions;
9281 }
9281 }
9282
9282
9283 /*!
9283 /*!
@@ -9289,10 +9289,10 void QCustomPlot::setInteractions(const
9289 */
9289 */
9290 void QCustomPlot::setInteraction(const QCP::Interaction &interaction, bool enabled)
9290 void QCustomPlot::setInteraction(const QCP::Interaction &interaction, bool enabled)
9291 {
9291 {
9292 if (!enabled && mInteractions.testFlag(interaction))
9292 if (!enabled && mInteractions.testFlag(interaction))
9293 mInteractions &= ~interaction;
9293 mInteractions &= ~interaction;
9294 else if (enabled && !mInteractions.testFlag(interaction))
9294 else if (enabled && !mInteractions.testFlag(interaction))
9295 mInteractions |= interaction;
9295 mInteractions |= interaction;
9296 }
9296 }
9297
9297
9298 /*!
9298 /*!
@@ -9310,7 +9310,7 void QCustomPlot::setInteraction(const Q
9310 */
9310 */
9311 void QCustomPlot::setSelectionTolerance(int pixels)
9311 void QCustomPlot::setSelectionTolerance(int pixels)
9312 {
9312 {
9313 mSelectionTolerance = pixels;
9313 mSelectionTolerance = pixels;
9314 }
9314 }
9315
9315
9316 /*!
9316 /*!
@@ -9324,7 +9324,7 void QCustomPlot::setSelectionTolerance(
9324 */
9324 */
9325 void QCustomPlot::setNoAntialiasingOnDrag(bool enabled)
9325 void QCustomPlot::setNoAntialiasingOnDrag(bool enabled)
9326 {
9326 {
9327 mNoAntialiasingOnDrag = enabled;
9327 mNoAntialiasingOnDrag = enabled;
9328 }
9328 }
9329
9329
9330 /*!
9330 /*!
@@ -9334,7 +9334,7 void QCustomPlot::setNoAntialiasingOnDra
9334 */
9334 */
9335 void QCustomPlot::setPlottingHints(const QCP::PlottingHints &hints)
9335 void QCustomPlot::setPlottingHints(const QCP::PlottingHints &hints)
9336 {
9336 {
9337 mPlottingHints = hints;
9337 mPlottingHints = hints;
9338 }
9338 }
9339
9339
9340 /*!
9340 /*!
@@ -9344,14 +9344,14 void QCustomPlot::setPlottingHints(const
9344 */
9344 */
9345 void QCustomPlot::setPlottingHint(QCP::PlottingHint hint, bool enabled)
9345 void QCustomPlot::setPlottingHint(QCP::PlottingHint hint, bool enabled)
9346 {
9346 {
9347 QCP::PlottingHints newHints = mPlottingHints;
9347 QCP::PlottingHints newHints = mPlottingHints;
9348 if (!enabled)
9348 if (!enabled)
9349 newHints &= ~hint;
9349 newHints &= ~hint;
9350 else
9350 else
9351 newHints |= hint;
9351 newHints |= hint;
9352
9352
9353 if (newHints != mPlottingHints)
9353 if (newHints != mPlottingHints)
9354 setPlottingHints(newHints);
9354 setPlottingHints(newHints);
9355 }
9355 }
9356
9356
9357 /*!
9357 /*!
@@ -9366,9 +9366,8 void QCustomPlot::setPlottingHint(QCP::P
9366 */
9366 */
9367 void QCustomPlot::setMultiSelectModifier(Qt::KeyboardModifier modifier)
9367 void QCustomPlot::setMultiSelectModifier(Qt::KeyboardModifier modifier)
9368 {
9368 {
9369 mMultiSelectModifier = modifier;
9369 mMultiSelectModifier = modifier;
9370 }
9370 }
9371
9372
9371
9373 /*!
9372 /*!
9374 Sets the viewport of this QCustomPlot. The Viewport is the area that the top level layout
9373 Sets the viewport of this QCustomPlot. The Viewport is the area that the top level layout
@@ -9379,9 +9378,9 void QCustomPlot::setMultiSelectModifier
9379 */
9378 */
9380 void QCustomPlot::setViewport(const QRect &rect)
9379 void QCustomPlot::setViewport(const QRect &rect)
9381 {
9380 {
9382 mViewport = rect;
9381 mViewport = rect;
9383 if (mPlotLayout)
9382 if (mPlotLayout)
9384 mPlotLayout->setOuterRect(mViewport);
9383 mPlotLayout->setOuterRect(mViewport);
9385 }
9384 }
9386
9385
9387 /*!
9386 /*!
@@ -9401,8 +9400,8 void QCustomPlot::setViewport(const QRec
9401 */
9400 */
9402 void QCustomPlot::setBackground(const QPixmap &pm)
9401 void QCustomPlot::setBackground(const QPixmap &pm)
9403 {
9402 {
9404 mBackgroundPixmap = pm;
9403 mBackgroundPixmap = pm;
9405 mScaledBackgroundPixmap = QPixmap();
9404 mScaledBackgroundPixmap = QPixmap();
9406 }
9405 }
9407
9406
9408 /*!
9407 /*!
@@ -9420,7 +9419,7 void QCustomPlot::setBackground(const QP
9420 */
9419 */
9421 void QCustomPlot::setBackground(const QBrush &brush)
9420 void QCustomPlot::setBackground(const QBrush &brush)
9422 {
9421 {
9423 mBackgroundBrush = brush;
9422 mBackgroundBrush = brush;
9424 }
9423 }
9425
9424
9426 /*! \overload
9425 /*! \overload
@@ -9432,10 +9431,10 void QCustomPlot::setBackground(const QB
9432 */
9431 */
9433 void QCustomPlot::setBackground(const QPixmap &pm, bool scaled, Qt::AspectRatioMode mode)
9432 void QCustomPlot::setBackground(const QPixmap &pm, bool scaled, Qt::AspectRatioMode mode)
9434 {
9433 {
9435 mBackgroundPixmap = pm;
9434 mBackgroundPixmap = pm;
9436 mScaledBackgroundPixmap = QPixmap();
9435 mScaledBackgroundPixmap = QPixmap();
9437 mBackgroundScaled = scaled;
9436 mBackgroundScaled = scaled;
9438 mBackgroundScaledMode = mode;
9437 mBackgroundScaledMode = mode;
9439 }
9438 }
9440
9439
9441 /*!
9440 /*!
@@ -9450,7 +9449,7 void QCustomPlot::setBackground(const QP
9450 */
9449 */
9451 void QCustomPlot::setBackgroundScaled(bool scaled)
9450 void QCustomPlot::setBackgroundScaled(bool scaled)
9452 {
9451 {
9453 mBackgroundScaled = scaled;
9452 mBackgroundScaled = scaled;
9454 }
9453 }
9455
9454
9456 /*!
9455 /*!
@@ -9461,7 +9460,7 void QCustomPlot::setBackgroundScaled(bo
9461 */
9460 */
9462 void QCustomPlot::setBackgroundScaledMode(Qt::AspectRatioMode mode)
9461 void QCustomPlot::setBackgroundScaledMode(Qt::AspectRatioMode mode)
9463 {
9462 {
9464 mBackgroundScaledMode = mode;
9463 mBackgroundScaledMode = mode;
9465 }
9464 }
9466
9465
9467 /*!
9466 /*!
@@ -9474,13 +9473,13 void QCustomPlot::setBackgroundScaledMod
9474 */
9473 */
9475 QCPAbstractPlottable *QCustomPlot::plottable(int index)
9474 QCPAbstractPlottable *QCustomPlot::plottable(int index)
9476 {
9475 {
9477 if (index >= 0 && index < mPlottables.size())
9476 if (index >= 0 && index < mPlottables.size())
9478 {
9477 {
9479 return mPlottables.at(index);
9478 return mPlottables.at(index);
9480 } else
9479 } else
9481 {
9480 {
9482 qDebug() << Q_FUNC_INFO << "index out of bounds:" << index;
9481 qDebug() << Q_FUNC_INFO << "index out of bounds:" << index;
9483 return 0;
9482 return 0;
9484 }
9483 }
9485 }
9484 }
9486
9485
@@ -9493,11 +9492,11 QCPAbstractPlottable *QCustomPlot::plott
9493 */
9492 */
9494 QCPAbstractPlottable *QCustomPlot::plottable()
9493 QCPAbstractPlottable *QCustomPlot::plottable()
9495 {
9494 {
9496 if (!mPlottables.isEmpty())
9495 if (!mPlottables.isEmpty())
9497 {
9496 {
9498 return mPlottables.last();
9497 return mPlottables.last();
9499 } else
9498 } else
9500 return 0;
9499 return 0;
9501 }
9500 }
9502
9501
9503 /*!
9502 /*!
@@ -9512,27 +9511,27 QCPAbstractPlottable *QCustomPlot::plott
9512 */
9511 */
9513 bool QCustomPlot::addPlottable(QCPAbstractPlottable *plottable)
9512 bool QCustomPlot::addPlottable(QCPAbstractPlottable *plottable)
9514 {
9513 {
9515 if (mPlottables.contains(plottable))
9514 if (mPlottables.contains(plottable))
9516 {
9515 {
9517 qDebug() << Q_FUNC_INFO << "plottable already added to this QCustomPlot:" << reinterpret_cast<quintptr>(plottable);
9516 qDebug() << Q_FUNC_INFO << "plottable already added to this QCustomPlot:" << reinterpret_cast<quintptr>(plottable);
9518 return false;
9517 return false;
9519 }
9518 }
9520 if (plottable->parentPlot() != this)
9519 if (plottable->parentPlot() != this)
9521 {
9520 {
9522 qDebug() << Q_FUNC_INFO << "plottable not created with this QCustomPlot as parent:" << reinterpret_cast<quintptr>(plottable);
9521 qDebug() << Q_FUNC_INFO << "plottable not created with this QCustomPlot as parent:" << reinterpret_cast<quintptr>(plottable);
9523 return false;
9522 return false;
9524 }
9523 }
9525
9524
9526 mPlottables.append(plottable);
9525 mPlottables.append(plottable);
9527 // possibly add plottable to legend:
9526 // possibly add plottable to legend:
9528 if (mAutoAddPlottableToLegend)
9527 if (mAutoAddPlottableToLegend)
9529 plottable->addToLegend();
9528 plottable->addToLegend();
9530 // special handling for QCPGraphs to maintain the simple graph interface:
9529 // special handling for QCPGraphs to maintain the simple graph interface:
9531 if (QCPGraph *graph = qobject_cast<QCPGraph*>(plottable))
9530 if (QCPGraph *graph = qobject_cast<QCPGraph*>(plottable))
9532 mGraphs.append(graph);
9531 mGraphs.append(graph);
9533 if (!plottable->layer()) // usually the layer is already set in the constructor of the plottable (via QCPLayerable constructor)
9532 if (!plottable->layer()) // usually the layer is already set in the constructor of the plottable (via QCPLayerable constructor)
9534 plottable->setLayer(currentLayer());
9533 plottable->setLayer(currentLayer());
9535 return true;
9534 return true;
9536 }
9535 }
9537
9536
9538 /*!
9537 /*!
@@ -9544,21 +9543,21 bool QCustomPlot::addPlottable(QCPAbstra
9544 */
9543 */
9545 bool QCustomPlot::removePlottable(QCPAbstractPlottable *plottable)
9544 bool QCustomPlot::removePlottable(QCPAbstractPlottable *plottable)
9546 {
9545 {
9547 if (!mPlottables.contains(plottable))
9546 if (!mPlottables.contains(plottable))
9548 {
9547 {
9549 qDebug() << Q_FUNC_INFO << "plottable not in list:" << reinterpret_cast<quintptr>(plottable);
9548 qDebug() << Q_FUNC_INFO << "plottable not in list:" << reinterpret_cast<quintptr>(plottable);
9550 return false;
9549 return false;
9551 }
9550 }
9552
9551
9553 // remove plottable from legend:
9552 // remove plottable from legend:
9554 plottable->removeFromLegend();
9553 plottable->removeFromLegend();
9555 // special handling for QCPGraphs to maintain the simple graph interface:
9554 // special handling for QCPGraphs to maintain the simple graph interface:
9556 if (QCPGraph *graph = qobject_cast<QCPGraph*>(plottable))
9555 if (QCPGraph *graph = qobject_cast<QCPGraph*>(plottable))
9557 mGraphs.removeOne(graph);
9556 mGraphs.removeOne(graph);
9558 // remove plottable:
9557 // remove plottable:
9559 delete plottable;
9558 delete plottable;
9560 mPlottables.removeOne(plottable);
9559 mPlottables.removeOne(plottable);
9561 return true;
9560 return true;
9562 }
9561 }
9563
9562
9564 /*! \overload
9563 /*! \overload
@@ -9567,12 +9566,12 bool QCustomPlot::removePlottable(QCPAbs
9567 */
9566 */
9568 bool QCustomPlot::removePlottable(int index)
9567 bool QCustomPlot::removePlottable(int index)
9569 {
9568 {
9570 if (index >= 0 && index < mPlottables.size())
9569 if (index >= 0 && index < mPlottables.size())
9571 return removePlottable(mPlottables[index]);
9570 return removePlottable(mPlottables[index]);
9572 else
9571 else
9573 {
9572 {
9574 qDebug() << Q_FUNC_INFO << "index out of bounds:" << index;
9573 qDebug() << Q_FUNC_INFO << "index out of bounds:" << index;
9575 return false;
9574 return false;
9576 }
9575 }
9577 }
9576 }
9578
9577
@@ -9585,10 +9584,10 bool QCustomPlot::removePlottable(int in
9585 */
9584 */
9586 int QCustomPlot::clearPlottables()
9585 int QCustomPlot::clearPlottables()
9587 {
9586 {
9588 int c = mPlottables.size();
9587 int c = mPlottables.size();
9589 for (int i=c-1; i >= 0; --i)
9588 for (int i=c-1; i >= 0; --i)
9590 removePlottable(mPlottables[i]);
9589 removePlottable(mPlottables[i]);
9591 return c;
9590 return c;
9592 }
9591 }
9593
9592
9594 /*!
9593 /*!
@@ -9598,7 +9597,7 int QCustomPlot::clearPlottables()
9598 */
9597 */
9599 int QCustomPlot::plottableCount() const
9598 int QCustomPlot::plottableCount() const
9600 {
9599 {
9601 return mPlottables.size();
9600 return mPlottables.size();
9602 }
9601 }
9603
9602
9604 /*!
9603 /*!
@@ -9610,13 +9609,13 int QCustomPlot::plottableCount() const
9610 */
9609 */
9611 QList<QCPAbstractPlottable*> QCustomPlot::selectedPlottables() const
9610 QList<QCPAbstractPlottable*> QCustomPlot::selectedPlottables() const
9612 {
9611 {
9613 QList<QCPAbstractPlottable*> result;
9612 QList<QCPAbstractPlottable*> result;
9614 foreach (QCPAbstractPlottable *plottable, mPlottables)
9613 foreach (QCPAbstractPlottable *plottable, mPlottables)
9615 {
9614 {
9616 if (plottable->selected())
9615 if (plottable->selected())
9617 result.append(plottable);
9616 result.append(plottable);
9618 }
9617 }
9619 return result;
9618 return result;
9620 }
9619 }
9621
9620
9622 /*!
9621 /*!
@@ -9633,25 +9632,25 QList<QCPAbstractPlottable*> QCustomPlot
9633 */
9632 */
9634 QCPAbstractPlottable *QCustomPlot::plottableAt(const QPointF &pos, bool onlySelectable) const
9633 QCPAbstractPlottable *QCustomPlot::plottableAt(const QPointF &pos, bool onlySelectable) const
9635 {
9634 {
9636 QCPAbstractPlottable *resultPlottable = 0;
9635 QCPAbstractPlottable *resultPlottable = 0;
9637 double resultDistance = mSelectionTolerance; // only regard clicks with distances smaller than mSelectionTolerance as selections, so initialize with that value
9636 double resultDistance = mSelectionTolerance; // only regard clicks with distances smaller than mSelectionTolerance as selections, so initialize with that value
9638
9637
9639 foreach (QCPAbstractPlottable *plottable, mPlottables)
9638 foreach (QCPAbstractPlottable *plottable, mPlottables)
9640 {
9639 {
9641 if (onlySelectable && !plottable->selectable()) // we could have also passed onlySelectable to the selectTest function, but checking here is faster, because we have access to QCPabstractPlottable::selectable
9640 if (onlySelectable && !plottable->selectable()) // we could have also passed onlySelectable to the selectTest function, but checking here is faster, because we have access to QCPabstractPlottable::selectable
9642 continue;
9641 continue;
9643 if ((plottable->keyAxis()->axisRect()->rect() & plottable->valueAxis()->axisRect()->rect()).contains(pos.toPoint())) // only consider clicks inside the rect that is spanned by the plottable's key/value axes
9642 if ((plottable->keyAxis()->axisRect()->rect() & plottable->valueAxis()->axisRect()->rect()).contains(pos.toPoint())) // only consider clicks inside the rect that is spanned by the plottable's key/value axes
9644 {
9643 {
9645 double currentDistance = plottable->selectTest(pos, false);
9644 double currentDistance = plottable->selectTest(pos, false);
9646 if (currentDistance >= 0 && currentDistance < resultDistance)
9645 if (currentDistance >= 0 && currentDistance < resultDistance)
9647 {
9646 {
9648 resultPlottable = plottable;
9647 resultPlottable = plottable;
9649 resultDistance = currentDistance;
9648 resultDistance = currentDistance;
9650 }
9649 }
9651 }
9650 }
9652 }
9651 }
9653
9652
9654 return resultPlottable;
9653 return resultPlottable;
9655 }
9654 }
9656
9655
9657 /*!
9656 /*!
@@ -9661,7 +9660,7 QCPAbstractPlottable *QCustomPlot::plott
9661 */
9660 */
9662 bool QCustomPlot::hasPlottable(QCPAbstractPlottable *plottable) const
9661 bool QCustomPlot::hasPlottable(QCPAbstractPlottable *plottable) const
9663 {
9662 {
9664 return mPlottables.contains(plottable);
9663 return mPlottables.contains(plottable);
9665 }
9664 }
9666
9665
9667 /*!
9666 /*!
@@ -9674,13 +9673,13 bool QCustomPlot::hasPlottable(QCPAbstra
9674 */
9673 */
9675 QCPGraph *QCustomPlot::graph(int index) const
9674 QCPGraph *QCustomPlot::graph(int index) const
9676 {
9675 {
9677 if (index >= 0 && index < mGraphs.size())
9676 if (index >= 0 && index < mGraphs.size())
9678 {
9677 {
9679 return mGraphs.at(index);
9678 return mGraphs.at(index);
9680 } else
9679 } else
9681 {
9680 {
9682 qDebug() << Q_FUNC_INFO << "index out of bounds:" << index;
9681 qDebug() << Q_FUNC_INFO << "index out of bounds:" << index;
9683 return 0;
9682 return 0;
9684 }
9683 }
9685 }
9684 }
9686
9685
@@ -9693,11 +9692,11 QCPGraph *QCustomPlot::graph(int index)
9693 */
9692 */
9694 QCPGraph *QCustomPlot::graph() const
9693 QCPGraph *QCustomPlot::graph() const
9695 {
9694 {
9696 if (!mGraphs.isEmpty())
9695 if (!mGraphs.isEmpty())
9697 {
9696 {
9698 return mGraphs.last();
9697 return mGraphs.last();
9699 } else
9698 } else
9700 return 0;
9699 return 0;
9701 }
9700 }
9702
9701
9703 /*!
9702 /*!
@@ -9714,28 +9713,28 QCPGraph *QCustomPlot::graph() const
9714 */
9713 */
9715 QCPGraph *QCustomPlot::addGraph(QCPAxis *keyAxis, QCPAxis *valueAxis)
9714 QCPGraph *QCustomPlot::addGraph(QCPAxis *keyAxis, QCPAxis *valueAxis)
9716 {
9715 {
9717 if (!keyAxis) keyAxis = xAxis;
9716 if (!keyAxis) keyAxis = xAxis;
9718 if (!valueAxis) valueAxis = yAxis;
9717 if (!valueAxis) valueAxis = yAxis;
9719 if (!keyAxis || !valueAxis)
9718 if (!keyAxis || !valueAxis)
9720 {
9719 {
9721 qDebug() << Q_FUNC_INFO << "can't use default QCustomPlot xAxis or yAxis, because at least one is invalid (has been deleted)";
9720 qDebug() << Q_FUNC_INFO << "can't use default QCustomPlot xAxis or yAxis, because at least one is invalid (has been deleted)";
9722 return 0;
9721 return 0;
9723 }
9722 }
9724 if (keyAxis->parentPlot() != this || valueAxis->parentPlot() != this)
9723 if (keyAxis->parentPlot() != this || valueAxis->parentPlot() != this)
9725 {
9724 {
9726 qDebug() << Q_FUNC_INFO << "passed keyAxis or valueAxis doesn't have this QCustomPlot as parent";
9725 qDebug() << Q_FUNC_INFO << "passed keyAxis or valueAxis doesn't have this QCustomPlot as parent";
9727 return 0;
9726 return 0;
9728 }
9727 }
9729
9728
9730 QCPGraph *newGraph = new QCPGraph(keyAxis, valueAxis);
9729 QCPGraph *newGraph = new QCPGraph(keyAxis, valueAxis);
9731 if (addPlottable(newGraph))
9730 if (addPlottable(newGraph))
9732 {
9731 {
9733 newGraph->setName(QLatin1String("Graph ")+QString::number(mGraphs.size()));
9732 newGraph->setName(QLatin1String("Graph ")+QString::number(mGraphs.size()));
9734 return newGraph;
9733 return newGraph;
9735 } else
9734 } else
9736 {
9735 {
9737 delete newGraph;
9736 delete newGraph;
9738 return 0;
9737 return 0;
9739 }
9738 }
9740 }
9739 }
9741
9740
@@ -9750,7 +9749,7 QCPGraph *QCustomPlot::addGraph(QCPAxis
9750 */
9749 */
9751 bool QCustomPlot::removeGraph(QCPGraph *graph)
9750 bool QCustomPlot::removeGraph(QCPGraph *graph)
9752 {
9751 {
9753 return removePlottable(graph);
9752 return removePlottable(graph);
9754 }
9753 }
9755
9754
9756 /*! \overload
9755 /*! \overload
@@ -9759,10 +9758,10 bool QCustomPlot::removeGraph(QCPGraph *
9759 */
9758 */
9760 bool QCustomPlot::removeGraph(int index)
9759 bool QCustomPlot::removeGraph(int index)
9761 {
9760 {
9762 if (index >= 0 && index < mGraphs.size())
9761 if (index >= 0 && index < mGraphs.size())
9763 return removeGraph(mGraphs[index]);
9762 return removeGraph(mGraphs[index]);
9764 else
9763 else
9765 return false;
9764 return false;
9766 }
9765 }
9767
9766
9768 /*!
9767 /*!
@@ -9774,10 +9773,10 bool QCustomPlot::removeGraph(int index)
9774 */
9773 */
9775 int QCustomPlot::clearGraphs()
9774 int QCustomPlot::clearGraphs()
9776 {
9775 {
9777 int c = mGraphs.size();
9776 int c = mGraphs.size();
9778 for (int i=c-1; i >= 0; --i)
9777 for (int i=c-1; i >= 0; --i)
9779 removeGraph(mGraphs[i]);
9778 removeGraph(mGraphs[i]);
9780 return c;
9779 return c;
9781 }
9780 }
9782
9781
9783 /*!
9782 /*!
@@ -9787,7 +9786,7 int QCustomPlot::clearGraphs()
9787 */
9786 */
9788 int QCustomPlot::graphCount() const
9787 int QCustomPlot::graphCount() const
9789 {
9788 {
9790 return mGraphs.size();
9789 return mGraphs.size();
9791 }
9790 }
9792
9791
9793 /*!
9792 /*!
@@ -9800,13 +9799,13 int QCustomPlot::graphCount() const
9800 */
9799 */
9801 QList<QCPGraph*> QCustomPlot::selectedGraphs() const
9800 QList<QCPGraph*> QCustomPlot::selectedGraphs() const
9802 {
9801 {
9803 QList<QCPGraph*> result;
9802 QList<QCPGraph*> result;
9804 foreach (QCPGraph *graph, mGraphs)
9803 foreach (QCPGraph *graph, mGraphs)
9805 {
9804 {
9806 if (graph->selected())
9805 if (graph->selected())
9807 result.append(graph);
9806 result.append(graph);
9808 }
9807 }
9809 return result;
9808 return result;
9810 }
9809 }
9811
9810
9812 /*!
9811 /*!
@@ -9819,13 +9818,13 QList<QCPGraph*> QCustomPlot::selectedGr
9819 */
9818 */
9820 QCPAbstractItem *QCustomPlot::item(int index) const
9819 QCPAbstractItem *QCustomPlot::item(int index) const
9821 {
9820 {
9822 if (index >= 0 && index < mItems.size())
9821 if (index >= 0 && index < mItems.size())
9823 {
9822 {
9824 return mItems.at(index);
9823 return mItems.at(index);
9825 } else
9824 } else
9826 {
9825 {
9827 qDebug() << Q_FUNC_INFO << "index out of bounds:" << index;
9826 qDebug() << Q_FUNC_INFO << "index out of bounds:" << index;
9828 return 0;
9827 return 0;
9829 }
9828 }
9830 }
9829 }
9831
9830
@@ -9838,11 +9837,11 QCPAbstractItem *QCustomPlot::item(int i
9838 */
9837 */
9839 QCPAbstractItem *QCustomPlot::item() const
9838 QCPAbstractItem *QCustomPlot::item() const
9840 {
9839 {
9841 if (!mItems.isEmpty())
9840 if (!mItems.isEmpty())
9842 {
9841 {
9843 return mItems.last();
9842 return mItems.last();
9844 } else
9843 } else
9845 return 0;
9844 return 0;
9846 }
9845 }
9847
9846
9848 /*!
9847 /*!
@@ -9855,14 +9854,14 QCPAbstractItem *QCustomPlot::item() con
9855 */
9854 */
9856 bool QCustomPlot::addItem(QCPAbstractItem *item)
9855 bool QCustomPlot::addItem(QCPAbstractItem *item)
9857 {
9856 {
9858 if (!mItems.contains(item) && item->parentPlot() == this)
9857 if (!mItems.contains(item) && item->parentPlot() == this)
9859 {
9858 {
9860 mItems.append(item);
9859 mItems.append(item);
9861 return true;
9860 return true;
9862 } else
9861 } else
9863 {
9862 {
9864 qDebug() << Q_FUNC_INFO << "item either already in list or not created with this QCustomPlot as parent:" << reinterpret_cast<quintptr>(item);
9863 qDebug() << Q_FUNC_INFO << "item either already in list or not created with this QCustomPlot as parent:" << reinterpret_cast<quintptr>(item);
9865 return false;
9864 return false;
9866 }
9865 }
9867 }
9866 }
9868
9867
@@ -9875,15 +9874,15 bool QCustomPlot::addItem(QCPAbstractIte
9875 */
9874 */
9876 bool QCustomPlot::removeItem(QCPAbstractItem *item)
9875 bool QCustomPlot::removeItem(QCPAbstractItem *item)
9877 {
9876 {
9878 if (mItems.contains(item))
9877 if (mItems.contains(item))
9879 {
9878 {
9880 delete item;
9879 delete item;
9881 mItems.removeOne(item);
9880 mItems.removeOne(item);
9882 return true;
9881 return true;
9883 } else
9882 } else
9884 {
9883 {
9885 qDebug() << Q_FUNC_INFO << "item not in list:" << reinterpret_cast<quintptr>(item);
9884 qDebug() << Q_FUNC_INFO << "item not in list:" << reinterpret_cast<quintptr>(item);
9886 return false;
9885 return false;
9887 }
9886 }
9888 }
9887 }
9889
9888
@@ -9893,12 +9892,12 bool QCustomPlot::removeItem(QCPAbstract
9893 */
9892 */
9894 bool QCustomPlot::removeItem(int index)
9893 bool QCustomPlot::removeItem(int index)
9895 {
9894 {
9896 if (index >= 0 && index < mItems.size())
9895 if (index >= 0 && index < mItems.size())
9897 return removeItem(mItems[index]);
9896 return removeItem(mItems[index]);
9898 else
9897 else
9899 {
9898 {
9900 qDebug() << Q_FUNC_INFO << "index out of bounds:" << index;
9899 qDebug() << Q_FUNC_INFO << "index out of bounds:" << index;
9901 return false;
9900 return false;
9902 }
9901 }
9903 }
9902 }
9904
9903
@@ -9911,10 +9910,10 bool QCustomPlot::removeItem(int index)
9911 */
9910 */
9912 int QCustomPlot::clearItems()
9911 int QCustomPlot::clearItems()
9913 {
9912 {
9914 int c = mItems.size();
9913 int c = mItems.size();
9915 for (int i=c-1; i >= 0; --i)
9914 for (int i=c-1; i >= 0; --i)
9916 removeItem(mItems[i]);
9915 removeItem(mItems[i]);
9917 return c;
9916 return c;
9918 }
9917 }
9919
9918
9920 /*!
9919 /*!
@@ -9924,7 +9923,7 int QCustomPlot::clearItems()
9924 */
9923 */
9925 int QCustomPlot::itemCount() const
9924 int QCustomPlot::itemCount() const
9926 {
9925 {
9927 return mItems.size();
9926 return mItems.size();
9928 }
9927 }
9929
9928
9930 /*!
9929 /*!
@@ -9934,13 +9933,13 int QCustomPlot::itemCount() const
9934 */
9933 */
9935 QList<QCPAbstractItem*> QCustomPlot::selectedItems() const
9934 QList<QCPAbstractItem*> QCustomPlot::selectedItems() const
9936 {
9935 {
9937 QList<QCPAbstractItem*> result;
9936 QList<QCPAbstractItem*> result;
9938 foreach (QCPAbstractItem *item, mItems)
9937 foreach (QCPAbstractItem *item, mItems)
9939 {
9938 {
9940 if (item->selected())
9939 if (item->selected())
9941 result.append(item);
9940 result.append(item);
9942 }
9941 }
9943 return result;
9942 return result;
9944 }
9943 }
9945
9944
9946 /*!
9945 /*!
@@ -9958,25 +9957,25 QList<QCPAbstractItem*> QCustomPlot::sel
9958 */
9957 */
9959 QCPAbstractItem *QCustomPlot::itemAt(const QPointF &pos, bool onlySelectable) const
9958 QCPAbstractItem *QCustomPlot::itemAt(const QPointF &pos, bool onlySelectable) const
9960 {
9959 {
9961 QCPAbstractItem *resultItem = 0;
9960 QCPAbstractItem *resultItem = 0;
9962 double resultDistance = mSelectionTolerance; // only regard clicks with distances smaller than mSelectionTolerance as selections, so initialize with that value
9961 double resultDistance = mSelectionTolerance; // only regard clicks with distances smaller than mSelectionTolerance as selections, so initialize with that value
9963
9962
9964 foreach (QCPAbstractItem *item, mItems)
9963 foreach (QCPAbstractItem *item, mItems)
9965 {
9964 {
9966 if (onlySelectable && !item->selectable()) // we could have also passed onlySelectable to the selectTest function, but checking here is faster, because we have access to QCPAbstractItem::selectable
9965 if (onlySelectable && !item->selectable()) // we could have also passed onlySelectable to the selectTest function, but checking here is faster, because we have access to QCPAbstractItem::selectable
9967 continue;
9966 continue;
9968 if (!item->clipToAxisRect() || item->clipRect().contains(pos.toPoint())) // only consider clicks inside axis cliprect of the item if actually clipped to it
9967 if (!item->clipToAxisRect() || item->clipRect().contains(pos.toPoint())) // only consider clicks inside axis cliprect of the item if actually clipped to it
9969 {
9968 {
9970 double currentDistance = item->selectTest(pos, false);
9969 double currentDistance = item->selectTest(pos, false);
9971 if (currentDistance >= 0 && currentDistance < resultDistance)
9970 if (currentDistance >= 0 && currentDistance < resultDistance)
9972 {
9971 {
9973 resultItem = item;
9972 resultItem = item;
9974 resultDistance = currentDistance;
9973 resultDistance = currentDistance;
9975 }
9974 }
9976 }
9975 }
9977 }
9976 }
9978
9977
9979 return resultItem;
9978 return resultItem;
9980 }
9979 }
9981
9980
9982 /*!
9981 /*!
@@ -9986,7 +9985,7 QCPAbstractItem *QCustomPlot::itemAt(con
9986 */
9985 */
9987 bool QCustomPlot::hasItem(QCPAbstractItem *item) const
9986 bool QCustomPlot::hasItem(QCPAbstractItem *item) const
9988 {
9987 {
9989 return mItems.contains(item);
9988 return mItems.contains(item);
9990 }
9989 }
9991
9990
9992 /*!
9991 /*!
@@ -9999,12 +9998,12 bool QCustomPlot::hasItem(QCPAbstractIte
9999 */
9998 */
10000 QCPLayer *QCustomPlot::layer(const QString &name) const
9999 QCPLayer *QCustomPlot::layer(const QString &name) const
10001 {
10000 {
10002 foreach (QCPLayer *layer, mLayers)
10001 foreach (QCPLayer *layer, mLayers)
10003 {
10002 {
10004 if (layer->name() == name)
10003 if (layer->name() == name)
10005 return layer;
10004 return layer;
10006 }
10005 }
10007 return 0;
10006 return 0;
10008 }
10007 }
10009
10008
10010 /*! \overload
10009 /*! \overload
@@ -10015,13 +10014,13 QCPLayer *QCustomPlot::layer(const QStri
10015 */
10014 */
10016 QCPLayer *QCustomPlot::layer(int index) const
10015 QCPLayer *QCustomPlot::layer(int index) const
10017 {
10016 {
10018 if (index >= 0 && index < mLayers.size())
10017 if (index >= 0 && index < mLayers.size())
10019 {
10018 {
10020 return mLayers.at(index);
10019 return mLayers.at(index);
10021 } else
10020 } else
10022 {
10021 {
10023 qDebug() << Q_FUNC_INFO << "index out of bounds:" << index;
10022 qDebug() << Q_FUNC_INFO << "index out of bounds:" << index;
10024 return 0;
10023 return 0;
10025 }
10024 }
10026 }
10025 }
10027
10026
@@ -10030,7 +10029,7 QCPLayer *QCustomPlot::layer(int index)
10030 */
10029 */
10031 QCPLayer *QCustomPlot::currentLayer() const
10030 QCPLayer *QCustomPlot::currentLayer() const
10032 {
10031 {
10033 return mCurrentLayer;
10032 return mCurrentLayer;
10034 }
10033 }
10035
10034
10036 /*!
10035 /*!
@@ -10045,13 +10044,13 QCPLayer *QCustomPlot::currentLayer() co
10045 */
10044 */
10046 bool QCustomPlot::setCurrentLayer(const QString &name)
10045 bool QCustomPlot::setCurrentLayer(const QString &name)
10047 {
10046 {
10048 if (QCPLayer *newCurrentLayer = layer(name))
10047 if (QCPLayer *newCurrentLayer = layer(name))
10049 {
10048 {
10050 return setCurrentLayer(newCurrentLayer);
10049 return setCurrentLayer(newCurrentLayer);
10051 } else
10050 } else
10052 {
10051 {
10053 qDebug() << Q_FUNC_INFO << "layer with name doesn't exist:" << name;
10052 qDebug() << Q_FUNC_INFO << "layer with name doesn't exist:" << name;
10054 return false;
10053 return false;
10055 }
10054 }
10056 }
10055 }
10057
10056
@@ -10065,14 +10064,14 bool QCustomPlot::setCurrentLayer(const
10065 */
10064 */
10066 bool QCustomPlot::setCurrentLayer(QCPLayer *layer)
10065 bool QCustomPlot::setCurrentLayer(QCPLayer *layer)
10067 {
10066 {
10068 if (!mLayers.contains(layer))
10067 if (!mLayers.contains(layer))
10069 {
10068 {
10070 qDebug() << Q_FUNC_INFO << "layer not a layer of this QCustomPlot:" << reinterpret_cast<quintptr>(layer);
10069 qDebug() << Q_FUNC_INFO << "layer not a layer of this QCustomPlot:" << reinterpret_cast<quintptr>(layer);
10071 return false;
10070 return false;
10072 }
10071 }
10073
10072
10074 mCurrentLayer = layer;
10073 mCurrentLayer = layer;
10075 return true;
10074 return true;
10076 }
10075 }
10077
10076
10078 /*!
10077 /*!
@@ -10082,7 +10081,7 bool QCustomPlot::setCurrentLayer(QCPLay
10082 */
10081 */
10083 int QCustomPlot::layerCount() const
10082 int QCustomPlot::layerCount() const
10084 {
10083 {
10085 return mLayers.size();
10084 return mLayers.size();
10086 }
10085 }
10087
10086
10088 /*!
10087 /*!
@@ -10100,23 +10099,23 int QCustomPlot::layerCount() const
10100 */
10099 */
10101 bool QCustomPlot::addLayer(const QString &name, QCPLayer *otherLayer, QCustomPlot::LayerInsertMode insertMode)
10100 bool QCustomPlot::addLayer(const QString &name, QCPLayer *otherLayer, QCustomPlot::LayerInsertMode insertMode)
10102 {
10101 {
10103 if (!otherLayer)
10102 if (!otherLayer)
10104 otherLayer = mLayers.last();
10103 otherLayer = mLayers.last();
10105 if (!mLayers.contains(otherLayer))
10104 if (!mLayers.contains(otherLayer))
10106 {
10105 {
10107 qDebug() << Q_FUNC_INFO << "otherLayer not a layer of this QCustomPlot:" << reinterpret_cast<quintptr>(otherLayer);
10106 qDebug() << Q_FUNC_INFO << "otherLayer not a layer of this QCustomPlot:" << reinterpret_cast<quintptr>(otherLayer);
10108 return false;
10107 return false;
10109 }
10108 }
10110 if (layer(name))
10109 if (layer(name))
10111 {
10110 {
10112 qDebug() << Q_FUNC_INFO << "A layer exists already with the name" << name;
10111 qDebug() << Q_FUNC_INFO << "A layer exists already with the name" << name;
10113 return false;
10112 return false;
10114 }
10113 }
10115
10114
10116 QCPLayer *newLayer = new QCPLayer(this, name);
10115 QCPLayer *newLayer = new QCPLayer(this, name);
10117 mLayers.insert(otherLayer->index() + (insertMode==limAbove ? 1:0), newLayer);
10116 mLayers.insert(otherLayer->index() + (insertMode==limAbove ? 1:0), newLayer);
10118 updateLayerIndices();
10117 updateLayerIndices();
10119 return true;
10118 return true;
10120 }
10119 }
10121
10120
10122 /*!
10121 /*!
@@ -10135,39 +10134,39 bool QCustomPlot::addLayer(const QString
10135 */
10134 */
10136 bool QCustomPlot::removeLayer(QCPLayer *layer)
10135 bool QCustomPlot::removeLayer(QCPLayer *layer)
10137 {
10136 {
10138 if (!mLayers.contains(layer))
10137 if (!mLayers.contains(layer))
10139 {
10138 {
10140 qDebug() << Q_FUNC_INFO << "layer not a layer of this QCustomPlot:" << reinterpret_cast<quintptr>(layer);
10139 qDebug() << Q_FUNC_INFO << "layer not a layer of this QCustomPlot:" << reinterpret_cast<quintptr>(layer);
10141 return false;
10140 return false;
10142 }
10141 }
10143 if (mLayers.size() < 2)
10142 if (mLayers.size() < 2)
10144 {
10143 {
10145 qDebug() << Q_FUNC_INFO << "can't remove last layer";
10144 qDebug() << Q_FUNC_INFO << "can't remove last layer";
10146 return false;
10145 return false;
10147 }
10146 }
10148
10147
10149 // append all children of this layer to layer below (if this is lowest layer, prepend to layer above)
10148 // append all children of this layer to layer below (if this is lowest layer, prepend to layer above)
10150 int removedIndex = layer->index();
10149 int removedIndex = layer->index();
10151 bool isFirstLayer = removedIndex==0;
10150 bool isFirstLayer = removedIndex==0;
10152 QCPLayer *targetLayer = isFirstLayer ? mLayers.at(removedIndex+1) : mLayers.at(removedIndex-1);
10151 QCPLayer *targetLayer = isFirstLayer ? mLayers.at(removedIndex+1) : mLayers.at(removedIndex-1);
10153 QList<QCPLayerable*> children = layer->children();
10152 QList<QCPLayerable*> children = layer->children();
10154 if (isFirstLayer) // prepend in reverse order (so order relative to each other stays the same)
10153 if (isFirstLayer) // prepend in reverse order (so order relative to each other stays the same)
10155 {
10154 {
10156 for (int i=children.size()-1; i>=0; --i)
10155 for (int i=children.size()-1; i>=0; --i)
10157 children.at(i)->moveToLayer(targetLayer, true);
10156 children.at(i)->moveToLayer(targetLayer, true);
10158 } else // append normally
10157 } else // append normally
10159 {
10158 {
10160 for (int i=0; i<children.size(); ++i)
10159 for (int i=0; i<children.size(); ++i)
10161 children.at(i)->moveToLayer(targetLayer, false);
10160 children.at(i)->moveToLayer(targetLayer, false);
10162 }
10161 }
10163 // if removed layer is current layer, change current layer to layer below/above:
10162 // if removed layer is current layer, change current layer to layer below/above:
10164 if (layer == mCurrentLayer)
10163 if (layer == mCurrentLayer)
10165 setCurrentLayer(targetLayer);
10164 setCurrentLayer(targetLayer);
10166 // remove layer:
10165 // remove layer:
10167 delete layer;
10166 delete layer;
10168 mLayers.removeOne(layer);
10167 mLayers.removeOne(layer);
10169 updateLayerIndices();
10168 updateLayerIndices();
10170 return true;
10169 return true;
10171 }
10170 }
10172
10171
10173 /*!
10172 /*!
@@ -10181,20 +10180,20 bool QCustomPlot::removeLayer(QCPLayer *
10181 */
10180 */
10182 bool QCustomPlot::moveLayer(QCPLayer *layer, QCPLayer *otherLayer, QCustomPlot::LayerInsertMode insertMode)
10181 bool QCustomPlot::moveLayer(QCPLayer *layer, QCPLayer *otherLayer, QCustomPlot::LayerInsertMode insertMode)
10183 {
10182 {
10184 if (!mLayers.contains(layer))
10183 if (!mLayers.contains(layer))
10185 {
10184 {
10186 qDebug() << Q_FUNC_INFO << "layer not a layer of this QCustomPlot:" << reinterpret_cast<quintptr>(layer);
10185 qDebug() << Q_FUNC_INFO << "layer not a layer of this QCustomPlot:" << reinterpret_cast<quintptr>(layer);
10187 return false;
10186 return false;
10188 }
10187 }
10189 if (!mLayers.contains(otherLayer))
10188 if (!mLayers.contains(otherLayer))
10190 {
10189 {
10191 qDebug() << Q_FUNC_INFO << "otherLayer not a layer of this QCustomPlot:" << reinterpret_cast<quintptr>(otherLayer);
10190 qDebug() << Q_FUNC_INFO << "otherLayer not a layer of this QCustomPlot:" << reinterpret_cast<quintptr>(otherLayer);
10192 return false;
10191 return false;
10193 }
10192 }
10194
10193
10195 mLayers.move(layer->index(), otherLayer->index() + (insertMode==limAbove ? 1:0));
10194 mLayers.move(layer->index(), otherLayer->index() + (insertMode==limAbove ? 1:0));
10196 updateLayerIndices();
10195 updateLayerIndices();
10197 return true;
10196 return true;
10198 }
10197 }
10199
10198
10200 /*!
10199 /*!
@@ -10208,7 +10207,7 bool QCustomPlot::moveLayer(QCPLayer *la
10208 */
10207 */
10209 int QCustomPlot::axisRectCount() const
10208 int QCustomPlot::axisRectCount() const
10210 {
10209 {
10211 return axisRects().size();
10210 return axisRects().size();
10212 }
10211 }
10213
10212
10214 /*!
10213 /*!
@@ -10222,14 +10221,14 int QCustomPlot::axisRectCount() const
10222 */
10221 */
10223 QCPAxisRect *QCustomPlot::axisRect(int index) const
10222 QCPAxisRect *QCustomPlot::axisRect(int index) const
10224 {
10223 {
10225 const QList<QCPAxisRect*> rectList = axisRects();
10224 const QList<QCPAxisRect*> rectList = axisRects();
10226 if (index >= 0 && index < rectList.size())
10225 if (index >= 0 && index < rectList.size())
10227 {
10226 {
10228 return rectList.at(index);
10227 return rectList.at(index);
10229 } else
10228 } else
10230 {
10229 {
10231 qDebug() << Q_FUNC_INFO << "invalid axis rect index" << index;
10230 qDebug() << Q_FUNC_INFO << "invalid axis rect index" << index;
10232 return 0;
10231 return 0;
10233 }
10232 }
10234 }
10233 }
10235
10234
@@ -10240,25 +10239,25 QCPAxisRect *QCustomPlot::axisRect(int i
10240 */
10239 */
10241 QList<QCPAxisRect*> QCustomPlot::axisRects() const
10240 QList<QCPAxisRect*> QCustomPlot::axisRects() const
10242 {
10241 {
10243 QList<QCPAxisRect*> result;
10242 QList<QCPAxisRect*> result;
10244 QStack<QCPLayoutElement*> elementStack;
10243 QStack<QCPLayoutElement*> elementStack;
10245 if (mPlotLayout)
10244 if (mPlotLayout)
10246 elementStack.push(mPlotLayout);
10245 elementStack.push(mPlotLayout);
10247
10246
10248 while (!elementStack.isEmpty())
10247 while (!elementStack.isEmpty())
10249 {
10248 {
10250 foreach (QCPLayoutElement *element, elementStack.pop()->elements(false))
10249 foreach (QCPLayoutElement *element, elementStack.pop()->elements(false))
10251 {
10250 {
10252 if (element)
10251 if (element)
10253 {
10252 {
10254 elementStack.push(element);
10253 elementStack.push(element);
10255 if (QCPAxisRect *ar = qobject_cast<QCPAxisRect*>(element))
10254 if (QCPAxisRect *ar = qobject_cast<QCPAxisRect*>(element))
10256 result.append(ar);
10255 result.append(ar);
10257 }
10256 }
10258 }
10257 }
10259 }
10258 }
10260
10259
10261 return result;
10260 return result;
10262 }
10261 }
10263
10262
10264 /*!
10263 /*!
@@ -10272,22 +10271,22 QList<QCPAxisRect*> QCustomPlot::axisRec
10272 */
10271 */
10273 QCPLayoutElement *QCustomPlot::layoutElementAt(const QPointF &pos) const
10272 QCPLayoutElement *QCustomPlot::layoutElementAt(const QPointF &pos) const
10274 {
10273 {
10275 QCPLayoutElement *currentElement = mPlotLayout;
10274 QCPLayoutElement *currentElement = mPlotLayout;
10276 bool searchSubElements = true;
10275 bool searchSubElements = true;
10277 while (searchSubElements && currentElement)
10276 while (searchSubElements && currentElement)
10278 {
10277 {
10279 searchSubElements = false;
10278 searchSubElements = false;
10280 foreach (QCPLayoutElement *subElement, currentElement->elements(false))
10279 foreach (QCPLayoutElement *subElement, currentElement->elements(false))
10281 {
10280 {
10282 if (subElement && subElement->realVisibility() && subElement->selectTest(pos, false) >= 0)
10281 if (subElement && subElement->realVisibility() && subElement->selectTest(pos, false) >= 0)
10283 {
10282 {
10284 currentElement = subElement;
10283 currentElement = subElement;
10285 searchSubElements = true;
10284 searchSubElements = true;
10286 break;
10285 break;
10287 }
10286 }
10288 }
10287 }
10289 }
10288 }
10290 return currentElement;
10289 return currentElement;
10291 }
10290 }
10292
10291
10293 /*!
10292 /*!
@@ -10299,17 +10298,17 QCPLayoutElement *QCustomPlot::layoutEle
10299 */
10298 */
10300 QList<QCPAxis*> QCustomPlot::selectedAxes() const
10299 QList<QCPAxis*> QCustomPlot::selectedAxes() const
10301 {
10300 {
10302 QList<QCPAxis*> result, allAxes;
10301 QList<QCPAxis*> result, allAxes;
10303 foreach (QCPAxisRect *rect, axisRects())
10302 foreach (QCPAxisRect *rect, axisRects())
10304 allAxes << rect->axes();
10303 allAxes << rect->axes();
10305
10304
10306 foreach (QCPAxis *axis, allAxes)
10305 foreach (QCPAxis *axis, allAxes)
10307 {
10306 {
10308 if (axis->selectedParts() != QCPAxis::spNone)
10307 if (axis->selectedParts() != QCPAxis::spNone)
10309 result.append(axis);
10308 result.append(axis);
10310 }
10309 }
10311
10310
10312 return result;
10311 return result;
10313 }
10312 }
10314
10313
10315 /*!
10314 /*!
@@ -10321,29 +10320,29 QList<QCPAxis*> QCustomPlot::selectedAxe
10321 */
10320 */
10322 QList<QCPLegend*> QCustomPlot::selectedLegends() const
10321 QList<QCPLegend*> QCustomPlot::selectedLegends() const
10323 {
10322 {
10324 QList<QCPLegend*> result;
10323 QList<QCPLegend*> result;
10325
10324
10326 QStack<QCPLayoutElement*> elementStack;
10325 QStack<QCPLayoutElement*> elementStack;
10327 if (mPlotLayout)
10326 if (mPlotLayout)
10328 elementStack.push(mPlotLayout);
10327 elementStack.push(mPlotLayout);
10329
10328
10330 while (!elementStack.isEmpty())
10329 while (!elementStack.isEmpty())
10331 {
10330 {
10332 foreach (QCPLayoutElement *subElement, elementStack.pop()->elements(false))
10331 foreach (QCPLayoutElement *subElement, elementStack.pop()->elements(false))
10333 {
10332 {
10334 if (subElement)
10333 if (subElement)
10335 {
10334 {
10336 elementStack.push(subElement);
10335 elementStack.push(subElement);
10337 if (QCPLegend *leg = qobject_cast<QCPLegend*>(subElement))
10336 if (QCPLegend *leg = qobject_cast<QCPLegend*>(subElement))
10338 {
10337 {
10339 if (leg->selectedParts() != QCPLegend::spNone)
10338 if (leg->selectedParts() != QCPLegend::spNone)
10340 result.append(leg);
10339 result.append(leg);
10341 }
10340 }
10342 }
10341 }
10343 }
10342 }
10344 }
10343 }
10345
10344
10346 return result;
10345 return result;
10347 }
10346 }
10348
10347
10349 /*!
10348 /*!
@@ -10357,10 +10356,10 QList<QCPLegend*> QCustomPlot::selectedL
10357 */
10356 */
10358 void QCustomPlot::deselectAll()
10357 void QCustomPlot::deselectAll()
10359 {
10358 {
10360 foreach (QCPLayer *layer, mLayers)
10359 foreach (QCPLayer *layer, mLayers)
10361 {
10360 {
10362 foreach (QCPLayerable *layerable, layer->children())
10361 foreach (QCPLayerable *layerable, layer->children())
10363 layerable->deselectEvent(0);
10362 layerable->deselectEvent(0);
10364 }
10363 }
10365 }
10364 }
10366
10365
@@ -10379,30 +10378,30 void QCustomPlot::deselectAll()
10379 */
10378 */
10380 void QCustomPlot::replot(QCustomPlot::RefreshPriority refreshPriority)
10379 void QCustomPlot::replot(QCustomPlot::RefreshPriority refreshPriority)
10381 {
10380 {
10382 if (mReplotting) // incase signals loop back to replot slot
10381 if (mReplotting) // incase signals loop back to replot slot
10383 return;
10382 return;
10384 mReplotting = true;
10383 mReplotting = true;
10385 emit beforeReplot();
10384 emit beforeReplot();
10386
10385
10387 mPaintBuffer.fill(mBackgroundBrush.style() == Qt::SolidPattern ? mBackgroundBrush.color() : Qt::transparent);
10386 mPaintBuffer.fill(mBackgroundBrush.style() == Qt::SolidPattern ? mBackgroundBrush.color() : Qt::transparent);
10388 QCPPainter painter;
10387 QCPPainter painter;
10389 painter.begin(&mPaintBuffer);
10388 painter.begin(&mPaintBuffer);
10390 if (painter.isActive())
10389 if (painter.isActive())
10391 {
10390 {
10392 painter.setRenderHint(QPainter::HighQualityAntialiasing); // to make Antialiasing look good if using the OpenGL graphicssystem
10391 painter.setRenderHint(QPainter::HighQualityAntialiasing); // to make Antialiasing look good if using the OpenGL graphicssystem
10393 if (mBackgroundBrush.style() != Qt::SolidPattern && mBackgroundBrush.style() != Qt::NoBrush)
10392 if (mBackgroundBrush.style() != Qt::SolidPattern && mBackgroundBrush.style() != Qt::NoBrush)
10394 painter.fillRect(mViewport, mBackgroundBrush);
10393 painter.fillRect(mViewport, mBackgroundBrush);
10395 draw(&painter);
10394 draw(&painter);
10396 painter.end();
10395 painter.end();
10397 if ((refreshPriority == rpHint && mPlottingHints.testFlag(QCP::phForceRepaint)) || refreshPriority==rpImmediate)
10396 if ((refreshPriority == rpHint && mPlottingHints.testFlag(QCP::phForceRepaint)) || refreshPriority==rpImmediate)
10398 repaint();
10397 repaint();
10399 else
10398 else
10400 update();
10399 update();
10401 } else // might happen if QCustomPlot has width or height zero
10400 } else // might happen if QCustomPlot has width or height zero
10402 qDebug() << Q_FUNC_INFO << "Couldn't activate painter on buffer. This usually happens because QCustomPlot has width or height zero.";
10401 qDebug() << Q_FUNC_INFO << "Couldn't activate painter on buffer. This usually happens because QCustomPlot has width or height zero.";
10403
10402
10404 emit afterReplot();
10403 emit afterReplot();
10405 mReplotting = false;
10404 mReplotting = false;
10406 }
10405 }
10407
10406
10408 /*!
10407 /*!
@@ -10415,12 +10414,12 void QCustomPlot::replot(QCustomPlot::Re
10415 */
10414 */
10416 void QCustomPlot::rescaleAxes(bool onlyVisiblePlottables)
10415 void QCustomPlot::rescaleAxes(bool onlyVisiblePlottables)
10417 {
10416 {
10418 QList<QCPAxis*> allAxes;
10417 QList<QCPAxis*> allAxes;
10419 foreach (QCPAxisRect *rect, axisRects())
10418 foreach (QCPAxisRect *rect, axisRects())
10420 allAxes << rect->axes();
10419 allAxes << rect->axes();
10421
10420
10422 foreach (QCPAxis *axis, allAxes)
10421 foreach (QCPAxis *axis, allAxes)
10423 axis->rescale(onlyVisiblePlottables);
10422 axis->rescale(onlyVisiblePlottables);
10424 }
10423 }
10425
10424
10426 /*!
10425 /*!
@@ -10462,63 +10461,63 void QCustomPlot::rescaleAxes(bool onlyV
10462 */
10461 */
10463 bool QCustomPlot::savePdf(const QString &fileName, bool noCosmeticPen, int width, int height, const QString &pdfCreator, const QString &pdfTitle)
10462 bool QCustomPlot::savePdf(const QString &fileName, bool noCosmeticPen, int width, int height, const QString &pdfCreator, const QString &pdfTitle)
10464 {
10463 {
10465 bool success = false;
10464 bool success = false;
10466 #ifdef QT_NO_PRINTER
10465 #ifdef QT_NO_PRINTER
10467 Q_UNUSED(fileName)
10466 Q_UNUSED(fileName)
10468 Q_UNUSED(noCosmeticPen)
10467 Q_UNUSED(noCosmeticPen)
10469 Q_UNUSED(width)
10468 Q_UNUSED(width)
10470 Q_UNUSED(height)
10469 Q_UNUSED(height)
10471 qDebug() << Q_FUNC_INFO << "Qt was built without printer support (QT_NO_PRINTER). PDF not created.";
10470 qDebug() << Q_FUNC_INFO << "Qt was built without printer support (QT_NO_PRINTER). PDF not created.";
10472 #else
10471 #else
10473 int newWidth, newHeight;
10472 int newWidth, newHeight;
10474 if (width == 0 || height == 0)
10473 if (width == 0 || height == 0)
10475 {
10474 {
10476 newWidth = this->width();
10475 newWidth = this->width();
10477 newHeight = this->height();
10476 newHeight = this->height();
10478 } else
10477 } else
10479 {
10478 {
10480 newWidth = width;
10479 newWidth = width;
10481 newHeight = height;
10480 newHeight = height;
10482 }
10481 }
10483
10482
10484 QPrinter printer(QPrinter::ScreenResolution);
10483 QPrinter printer(QPrinter::ScreenResolution);
10485 printer.setOutputFileName(fileName);
10484 printer.setOutputFileName(fileName);
10486 printer.setOutputFormat(QPrinter::PdfFormat);
10485 printer.setOutputFormat(QPrinter::PdfFormat);
10487 printer.setColorMode(QPrinter::Color);
10486 printer.setColorMode(QPrinter::Color);
10488 printer.printEngine()->setProperty(QPrintEngine::PPK_Creator, pdfCreator);
10487 printer.printEngine()->setProperty(QPrintEngine::PPK_Creator, pdfCreator);
10489 printer.printEngine()->setProperty(QPrintEngine::PPK_DocumentName, pdfTitle);
10488 printer.printEngine()->setProperty(QPrintEngine::PPK_DocumentName, pdfTitle);
10490 QRect oldViewport = viewport();
10489 QRect oldViewport = viewport();
10491 setViewport(QRect(0, 0, newWidth, newHeight));
10490 setViewport(QRect(0, 0, newWidth, newHeight));
10492 #if QT_VERSION < QT_VERSION_CHECK(5, 3, 0)
10491 #if QT_VERSION < QT_VERSION_CHECK(5, 3, 0)
10493 printer.setFullPage(true);
10492 printer.setFullPage(true);
10494 printer.setPaperSize(viewport().size(), QPrinter::DevicePixel);
10493 printer.setPaperSize(viewport().size(), QPrinter::DevicePixel);
10495 #else
10494 #else
10496 QPageLayout pageLayout;
10495 QPageLayout pageLayout;
10497 pageLayout.setMode(QPageLayout::FullPageMode);
10496 pageLayout.setMode(QPageLayout::FullPageMode);
10498 pageLayout.setOrientation(QPageLayout::Portrait);
10497 pageLayout.setOrientation(QPageLayout::Portrait);
10499 pageLayout.setMargins(QMarginsF(0, 0, 0, 0));
10498 pageLayout.setMargins(QMarginsF(0, 0, 0, 0));
10500 pageLayout.setPageSize(QPageSize(viewport().size(), QPageSize::Point, QString(), QPageSize::ExactMatch));
10499 pageLayout.setPageSize(QPageSize(viewport().size(), QPageSize::Point, QString(), QPageSize::ExactMatch));
10501 printer.setPageLayout(pageLayout);
10500 printer.setPageLayout(pageLayout);
10502 #endif
10501 #endif
10503 QCPPainter printpainter;
10502 QCPPainter printpainter;
10504 if (printpainter.begin(&printer))
10503 if (printpainter.begin(&printer))
10505 {
10504 {
10506 printpainter.setMode(QCPPainter::pmVectorized);
10505 printpainter.setMode(QCPPainter::pmVectorized);
10507 printpainter.setMode(QCPPainter::pmNoCaching);
10506 printpainter.setMode(QCPPainter::pmNoCaching);
10508 printpainter.setMode(QCPPainter::pmNonCosmetic, noCosmeticPen);
10507 printpainter.setMode(QCPPainter::pmNonCosmetic, noCosmeticPen);
10509 printpainter.setWindow(mViewport);
10508 printpainter.setWindow(mViewport);
10510 if (mBackgroundBrush.style() != Qt::NoBrush &&
10509 if (mBackgroundBrush.style() != Qt::NoBrush &&
10511 mBackgroundBrush.color() != Qt::white &&
10510 mBackgroundBrush.color() != Qt::white &&
10512 mBackgroundBrush.color() != Qt::transparent &&
10511 mBackgroundBrush.color() != Qt::transparent &&
10513 mBackgroundBrush.color().alpha() > 0) // draw pdf background color if not white/transparent
10512 mBackgroundBrush.color().alpha() > 0) // draw pdf background color if not white/transparent
10514 printpainter.fillRect(viewport(), mBackgroundBrush);
10513 printpainter.fillRect(viewport(), mBackgroundBrush);
10515 draw(&printpainter);
10514 draw(&printpainter);
10516 printpainter.end();
10515 printpainter.end();
10517 success = true;
10516 success = true;
10518 }
10517 }
10519 setViewport(oldViewport);
10518 setViewport(oldViewport);
10520 #endif // QT_NO_PRINTER
10519 #endif // QT_NO_PRINTER
10521 return success;
10520 return success;
10522 }
10521 }
10523
10522
10524 /*!
10523 /*!
@@ -10560,7 +10559,7 bool QCustomPlot::savePdf(const QString
10560 */
10559 */
10561 bool QCustomPlot::savePng(const QString &fileName, int width, int height, double scale, int quality)
10560 bool QCustomPlot::savePng(const QString &fileName, int width, int height, double scale, int quality)
10562 {
10561 {
10563 return saveRastered(fileName, width, height, scale, "PNG", quality);
10562 return saveRastered(fileName, width, height, scale, "PNG", quality);
10564 }
10563 }
10565
10564
10566 /*!
10565 /*!
@@ -10599,7 +10598,7 bool QCustomPlot::savePng(const QString
10599 */
10598 */
10600 bool QCustomPlot::saveJpg(const QString &fileName, int width, int height, double scale, int quality)
10599 bool QCustomPlot::saveJpg(const QString &fileName, int width, int height, double scale, int quality)
10601 {
10600 {
10602 return saveRastered(fileName, width, height, scale, "JPG", quality);
10601 return saveRastered(fileName, width, height, scale, "JPG", quality);
10603 }
10602 }
10604
10603
10605 /*!
10604 /*!
@@ -10635,7 +10634,7 bool QCustomPlot::saveJpg(const QString
10635 */
10634 */
10636 bool QCustomPlot::saveBmp(const QString &fileName, int width, int height, double scale)
10635 bool QCustomPlot::saveBmp(const QString &fileName, int width, int height, double scale)
10637 {
10636 {
10638 return saveRastered(fileName, width, height, scale, "BMP");
10637 return saveRastered(fileName, width, height, scale, "BMP");
10639 }
10638 }
10640
10639
10641 /*! \internal
10640 /*! \internal
@@ -10648,7 +10647,7 bool QCustomPlot::saveBmp(const QString
10648 */
10647 */
10649 QSize QCustomPlot::minimumSizeHint() const
10648 QSize QCustomPlot::minimumSizeHint() const
10650 {
10649 {
10651 return mPlotLayout->minimumSizeHint();
10650 return mPlotLayout->minimumSizeHint();
10652 }
10651 }
10653
10652
10654 /*! \internal
10653 /*! \internal
@@ -10658,7 +10657,7 QSize QCustomPlot::minimumSizeHint() con
10658 */
10657 */
10659 QSize QCustomPlot::sizeHint() const
10658 QSize QCustomPlot::sizeHint() const
10660 {
10659 {
10661 return mPlotLayout->minimumSizeHint();
10660 return mPlotLayout->minimumSizeHint();
10662 }
10661 }
10663
10662
10664 /*! \internal
10663 /*! \internal
@@ -10668,9 +10667,9 QSize QCustomPlot::sizeHint() const
10668 */
10667 */
10669 void QCustomPlot::paintEvent(QPaintEvent *event)
10668 void QCustomPlot::paintEvent(QPaintEvent *event)
10670 {
10669 {
10671 Q_UNUSED(event);
10670 Q_UNUSED(event);
10672 QPainter painter(this);
10671 QPainter painter(this);
10673 painter.drawPixmap(0, 0, mPaintBuffer);
10672 painter.drawPixmap(0, 0, mPaintBuffer);
10674 }
10673 }
10675
10674
10676 /*! \internal
10675 /*! \internal
@@ -10681,17 +10680,10 void QCustomPlot::paintEvent(QPaintEvent
10681 */
10680 */
10682 void QCustomPlot::resizeEvent(QResizeEvent *event)
10681 void QCustomPlot::resizeEvent(QResizeEvent *event)
10683 {
10682 {
10684 // resize and repaint the buffer:
10683 // resize and repaint the buffer:
10685 mPaintBuffer = QPixmap(event->size());
10684 mPaintBuffer = QPixmap(event->size());
10686 setViewport(rect());
10685 setViewport(rect());
10687 replot(rpQueued); // queued update is important here, to prevent painting issues in some contexts
10686 replot(rpQueued); // queued update is important here, to prevent painting issues in some contexts
10688 // resize and repaint the buffer:
10689 // QSize pbSize = event->size();
10690 // pbSize *= devicePixelRatio();
10691 // mPaintBuffer = QPixmap(pbSize);
10692 // mPaintBuffer.setDevicePixelRatio(devicePixelRatio());
10693 // setViewport(rect());
10694 // replot(rpQueued); // queued update is important here, to prevent painting issues in some contexts
10695 }
10687 }
10696
10688
10697 /*! \internal
10689 /*! \internal
@@ -10705,37 +10697,37 void QCustomPlot::resizeEvent(QResizeEve
10705 */
10697 */
10706 void QCustomPlot::mouseDoubleClickEvent(QMouseEvent *event)
10698 void QCustomPlot::mouseDoubleClickEvent(QMouseEvent *event)
10707 {
10699 {
10708 emit mouseDoubleClick(event);
10700 emit mouseDoubleClick(event);
10709
10701
10710 QVariant details;
10702 QVariant details;
10711 QCPLayerable *clickedLayerable = layerableAt(event->pos(), false, &details);
10703 QCPLayerable *clickedLayerable = layerableAt(event->pos(), false, &details);
10712
10704
10713 // emit specialized object double click signals:
10705 // emit specialized object double click signals:
10714 if (QCPAbstractPlottable *ap = qobject_cast<QCPAbstractPlottable*>(clickedLayerable))
10706 if (QCPAbstractPlottable *ap = qobject_cast<QCPAbstractPlottable*>(clickedLayerable))
10715 emit plottableDoubleClick(ap, event);
10707 emit plottableDoubleClick(ap, event);
10716 else if (QCPAxis *ax = qobject_cast<QCPAxis*>(clickedLayerable))
10708 else if (QCPAxis *ax = qobject_cast<QCPAxis*>(clickedLayerable))
10717 emit axisDoubleClick(ax, details.value<QCPAxis::SelectablePart>(), event);
10709 emit axisDoubleClick(ax, details.value<QCPAxis::SelectablePart>(), event);
10718 else if (QCPAbstractItem *ai = qobject_cast<QCPAbstractItem*>(clickedLayerable))
10710 else if (QCPAbstractItem *ai = qobject_cast<QCPAbstractItem*>(clickedLayerable))
10719 emit itemDoubleClick(ai, event);
10711 emit itemDoubleClick(ai, event);
10720 else if (QCPLegend *lg = qobject_cast<QCPLegend*>(clickedLayerable))
10712 else if (QCPLegend *lg = qobject_cast<QCPLegend*>(clickedLayerable))
10721 emit legendDoubleClick(lg, 0, event);
10713 emit legendDoubleClick(lg, 0, event);
10722 else if (QCPAbstractLegendItem *li = qobject_cast<QCPAbstractLegendItem*>(clickedLayerable))
10714 else if (QCPAbstractLegendItem *li = qobject_cast<QCPAbstractLegendItem*>(clickedLayerable))
10723 emit legendDoubleClick(li->parentLegend(), li, event);
10715 emit legendDoubleClick(li->parentLegend(), li, event);
10724 else if (QCPPlotTitle *pt = qobject_cast<QCPPlotTitle*>(clickedLayerable))
10716 else if (QCPPlotTitle *pt = qobject_cast<QCPPlotTitle*>(clickedLayerable))
10725 emit titleDoubleClick(event, pt);
10717 emit titleDoubleClick(event, pt);
10726
10718
10727 // call double click event of affected layout element:
10719 // call double click event of affected layout element:
10728 if (QCPLayoutElement *el = layoutElementAt(event->pos()))
10720 if (QCPLayoutElement *el = layoutElementAt(event->pos()))
10729 el->mouseDoubleClickEvent(event);
10721 el->mouseDoubleClickEvent(event);
10730
10722
10731 // call release event of affected layout element (as in mouseReleaseEvent, since the mouseDoubleClick replaces the second release event in double click case):
10723 // call release event of affected layout element (as in mouseReleaseEvent, since the mouseDoubleClick replaces the second release event in double click case):
10732 if (mMouseEventElement)
10724 if (mMouseEventElement)
10733 {
10725 {
10734 mMouseEventElement->mouseReleaseEvent(event);
10726 mMouseEventElement->mouseReleaseEvent(event);
10735 mMouseEventElement = 0;
10727 mMouseEventElement = 0;
10736 }
10728 }
10737
10729
10738 //QWidget::mouseDoubleClickEvent(event); don't call base class implementation because it would just cause a mousePress/ReleaseEvent, which we don't want.
10730 //QWidget::mouseDoubleClickEvent(event); don't call base class implementation because it would just cause a mousePress/ReleaseEvent, which we don't want.
10739 }
10731 }
10740
10732
10741 /*! \internal
10733 /*! \internal
@@ -10747,15 +10739,15 void QCustomPlot::mouseDoubleClickEvent(
10747 */
10739 */
10748 void QCustomPlot::mousePressEvent(QMouseEvent *event)
10740 void QCustomPlot::mousePressEvent(QMouseEvent *event)
10749 {
10741 {
10750 emit mousePress(event);
10742 emit mousePress(event);
10751 mMousePressPos = event->pos(); // need this to determine in releaseEvent whether it was a click (no position change between press and release)
10743 mMousePressPos = event->pos(); // need this to determine in releaseEvent whether it was a click (no position change between press and release)
10752
10744
10753 // call event of affected layout element:
10745 // call event of affected layout element:
10754 mMouseEventElement = layoutElementAt(event->pos());
10746 mMouseEventElement = layoutElementAt(event->pos());
10755 if (mMouseEventElement)
10747 if (mMouseEventElement)
10756 mMouseEventElement->mousePressEvent(event);
10748 mMouseEventElement->mousePressEvent(event);
10757
10749
10758 QWidget::mousePressEvent(event);
10750 QWidget::mousePressEvent(event);
10759 }
10751 }
10760
10752
10761 /*! \internal
10753 /*! \internal
@@ -10769,13 +10761,13 void QCustomPlot::mousePressEvent(QMouse
10769 */
10761 */
10770 void QCustomPlot::mouseMoveEvent(QMouseEvent *event)
10762 void QCustomPlot::mouseMoveEvent(QMouseEvent *event)
10771 {
10763 {
10772 emit mouseMove(event);
10764 emit mouseMove(event);
10773
10765
10774 // call event of affected layout element:
10766 // call event of affected layout element:
10775 if (mMouseEventElement)
10767 if (mMouseEventElement)
10776 mMouseEventElement->mouseMoveEvent(event);
10768 mMouseEventElement->mouseMoveEvent(event);
10777
10769
10778 QWidget::mouseMoveEvent(event);
10770 QWidget::mouseMoveEvent(event);
10779 }
10771 }
10780
10772
10781 /*! \internal
10773 /*! \internal
@@ -10794,74 +10786,74 void QCustomPlot::mouseMoveEvent(QMouseE
10794 */
10786 */
10795 void QCustomPlot::mouseReleaseEvent(QMouseEvent *event)
10787 void QCustomPlot::mouseReleaseEvent(QMouseEvent *event)
10796 {
10788 {
10797 emit mouseRelease(event);
10789 emit mouseRelease(event);
10798 bool doReplot = false;
10790 bool doReplot = false;
10799
10791
10800 if ((mMousePressPos-event->pos()).manhattanLength() < 5) // determine whether it was a click operation
10792 if ((mMousePressPos-event->pos()).manhattanLength() < 5) // determine whether it was a click operation
10801 {
10793 {
10802 if (event->button() == Qt::LeftButton)
10794 if (event->button() == Qt::LeftButton)
10803 {
10795 {
10804 // handle selection mechanism:
10796 // handle selection mechanism:
10805 QVariant details;
10797 QVariant details;
10806 QCPLayerable *clickedLayerable = layerableAt(event->pos(), true, &details);
10798 QCPLayerable *clickedLayerable = layerableAt(event->pos(), true, &details);
10807 bool selectionStateChanged = false;
10799 bool selectionStateChanged = false;
10808 bool additive = mInteractions.testFlag(QCP::iMultiSelect) && event->modifiers().testFlag(mMultiSelectModifier);
10800 bool additive = mInteractions.testFlag(QCP::iMultiSelect) && event->modifiers().testFlag(mMultiSelectModifier);
10809 // deselect all other layerables if not additive selection:
10801 // deselect all other layerables if not additive selection:
10810 if (!additive)
10802 if (!additive)
10811 {
10803 {
10812 foreach (QCPLayer *layer, mLayers)
10804 foreach (QCPLayer *layer, mLayers)
10813 {
10805 {
10814 foreach (QCPLayerable *layerable, layer->children())
10806 foreach (QCPLayerable *layerable, layer->children())
10815 {
10807 {
10816 if (layerable != clickedLayerable && mInteractions.testFlag(layerable->selectionCategory()))
10808 if (layerable != clickedLayerable && mInteractions.testFlag(layerable->selectionCategory()))
10817 {
10809 {
10818 bool selChanged = false;
10810 bool selChanged = false;
10819 layerable->deselectEvent(&selChanged);
10811 layerable->deselectEvent(&selChanged);
10820 selectionStateChanged |= selChanged;
10812 selectionStateChanged |= selChanged;
10821 }
10813 }
10822 }
10814 }
10823 }
10815 }
10824 }
10816 }
10825 if (clickedLayerable && mInteractions.testFlag(clickedLayerable->selectionCategory()))
10817 if (clickedLayerable && mInteractions.testFlag(clickedLayerable->selectionCategory()))
10826 {
10818 {
10827 // a layerable was actually clicked, call its selectEvent:
10819 // a layerable was actually clicked, call its selectEvent:
10828 bool selChanged = false;
10820 bool selChanged = false;
10829 clickedLayerable->selectEvent(event, additive, details, &selChanged);
10821 clickedLayerable->selectEvent(event, additive, details, &selChanged);
10830 selectionStateChanged |= selChanged;
10822 selectionStateChanged |= selChanged;
10831 }
10823 }
10832 doReplot = true;
10824 doReplot = true;
10833 if (selectionStateChanged)
10825 if (selectionStateChanged)
10834 emit selectionChangedByUser();
10826 emit selectionChangedByUser();
10835 }
10827 }
10836
10828
10837 // emit specialized object click signals:
10829 // emit specialized object click signals:
10838 QVariant details;
10830 QVariant details;
10839 QCPLayerable *clickedLayerable = layerableAt(event->pos(), false, &details); // for these signals, selectability is ignored, that's why we call this again with onlySelectable set to false
10831 QCPLayerable *clickedLayerable = layerableAt(event->pos(), false, &details); // for these signals, selectability is ignored, that's why we call this again with onlySelectable set to false
10840 if (QCPAbstractPlottable *ap = qobject_cast<QCPAbstractPlottable*>(clickedLayerable))
10832 if (QCPAbstractPlottable *ap = qobject_cast<QCPAbstractPlottable*>(clickedLayerable))
10841 emit plottableClick(ap, event);
10833 emit plottableClick(ap, event);
10842 else if (QCPAxis *ax = qobject_cast<QCPAxis*>(clickedLayerable))
10834 else if (QCPAxis *ax = qobject_cast<QCPAxis*>(clickedLayerable))
10843 emit axisClick(ax, details.value<QCPAxis::SelectablePart>(), event);
10835 emit axisClick(ax, details.value<QCPAxis::SelectablePart>(), event);
10844 else if (QCPAbstractItem *ai = qobject_cast<QCPAbstractItem*>(clickedLayerable))
10836 else if (QCPAbstractItem *ai = qobject_cast<QCPAbstractItem*>(clickedLayerable))
10845 emit itemClick(ai, event);
10837 emit itemClick(ai, event);
10846 else if (QCPLegend *lg = qobject_cast<QCPLegend*>(clickedLayerable))
10838 else if (QCPLegend *lg = qobject_cast<QCPLegend*>(clickedLayerable))
10847 emit legendClick(lg, 0, event);
10839 emit legendClick(lg, 0, event);
10848 else if (QCPAbstractLegendItem *li = qobject_cast<QCPAbstractLegendItem*>(clickedLayerable))
10840 else if (QCPAbstractLegendItem *li = qobject_cast<QCPAbstractLegendItem*>(clickedLayerable))
10849 emit legendClick(li->parentLegend(), li, event);
10841 emit legendClick(li->parentLegend(), li, event);
10850 else if (QCPPlotTitle *pt = qobject_cast<QCPPlotTitle*>(clickedLayerable))
10842 else if (QCPPlotTitle *pt = qobject_cast<QCPPlotTitle*>(clickedLayerable))
10851 emit titleClick(event, pt);
10843 emit titleClick(event, pt);
10852 }
10844 }
10853
10845
10854 // call event of affected layout element:
10846 // call event of affected layout element:
10855 if (mMouseEventElement)
10847 if (mMouseEventElement)
10856 {
10848 {
10857 mMouseEventElement->mouseReleaseEvent(event);
10849 mMouseEventElement->mouseReleaseEvent(event);
10858 mMouseEventElement = 0;
10850 mMouseEventElement = 0;
10859 }
10851 }
10860
10852
10861 if (doReplot || noAntialiasingOnDrag())
10853 if (doReplot || noAntialiasingOnDrag())
10862 replot();
10854 replot();
10863
10855
10864 QWidget::mouseReleaseEvent(event);
10856 QWidget::mouseReleaseEvent(event);
10865 }
10857 }
10866
10858
10867 /*! \internal
10859 /*! \internal
@@ -10872,13 +10864,13 void QCustomPlot::mouseReleaseEvent(QMou
10872 */
10864 */
10873 void QCustomPlot::wheelEvent(QWheelEvent *event)
10865 void QCustomPlot::wheelEvent(QWheelEvent *event)
10874 {
10866 {
10875 emit mouseWheel(event);
10867 emit mouseWheel(event);
10876
10868
10877 // call event of affected layout element:
10869 // call event of affected layout element:
10878 if (QCPLayoutElement *el = layoutElementAt(event->pos()))
10870 if (QCPLayoutElement *el = layoutElementAt(event->pos()))
10879 el->wheelEvent(event);
10871 el->wheelEvent(event);
10880
10872
10881 QWidget::wheelEvent(event);
10873 QWidget::wheelEvent(event);
10882 }
10874 }
10883
10875
10884 /*! \internal
10876 /*! \internal
@@ -10890,31 +10882,31 void QCustomPlot::wheelEvent(QWheelEvent
10890 */
10882 */
10891 void QCustomPlot::draw(QCPPainter *painter)
10883 void QCustomPlot::draw(QCPPainter *painter)
10892 {
10884 {
10893 // run through layout phases:
10885 // run through layout phases:
10894 mPlotLayout->update(QCPLayoutElement::upPreparation);
10886 mPlotLayout->update(QCPLayoutElement::upPreparation);
10895 mPlotLayout->update(QCPLayoutElement::upMargins);
10887 mPlotLayout->update(QCPLayoutElement::upMargins);
10896 mPlotLayout->update(QCPLayoutElement::upLayout);
10888 mPlotLayout->update(QCPLayoutElement::upLayout);
10897
10889
10898 // draw viewport background pixmap:
10890 // draw viewport background pixmap:
10899 drawBackground(painter);
10891 drawBackground(painter);
10900
10892
10901 // draw all layered objects (grid, axes, plottables, items, legend,...):
10893 // draw all layered objects (grid, axes, plottables, items, legend,...):
10902 foreach (QCPLayer *layer, mLayers)
10894 foreach (QCPLayer *layer, mLayers)
10903 {
10895 {
10904 foreach (QCPLayerable *child, layer->children())
10896 foreach (QCPLayerable *child, layer->children())
10905 {
10897 {
10906 if (child->realVisibility())
10898 if (child->realVisibility())
10907 {
10899 {
10908 painter->save();
10900 painter->save();
10909 painter->setClipRect(child->clipRect().translated(0, -1));
10901 painter->setClipRect(child->clipRect().translated(0, -1));
10910 child->applyDefaultAntialiasingHint(painter);
10902 child->applyDefaultAntialiasingHint(painter);
10911 child->draw(painter);
10903 child->draw(painter);
10912 painter->restore();
10904 painter->restore();
10913 }
10905 }
10914 }
10906 }
10915 }
10907 }
10916
10908
10917 /* Debug code to draw all layout element rects
10909 /* Debug code to draw all layout element rects
10918 foreach (QCPLayoutElement* el, findChildren<QCPLayoutElement*>())
10910 foreach (QCPLayoutElement* el, findChildren<QCPLayoutElement*>())
10919 {
10911 {
10920 painter->setBrush(Qt::NoBrush);
10912 painter->setBrush(Qt::NoBrush);
@@ -10945,22 +10937,22 void QCustomPlot::draw(QCPPainter *paint
10945 */
10937 */
10946 void QCustomPlot::drawBackground(QCPPainter *painter)
10938 void QCustomPlot::drawBackground(QCPPainter *painter)
10947 {
10939 {
10948 // Note: background color is handled in individual replot/save functions
10940 // Note: background color is handled in individual replot/save functions
10949
10941
10950 // draw background pixmap (on top of fill, if brush specified):
10942 // draw background pixmap (on top of fill, if brush specified):
10951 if (!mBackgroundPixmap.isNull())
10943 if (!mBackgroundPixmap.isNull())
10952 {
10944 {
10953 if (mBackgroundScaled)
10945 if (mBackgroundScaled)
10954 {
10946 {
10955 // check whether mScaledBackground needs to be updated:
10947 // check whether mScaledBackground needs to be updated:
10956 QSize scaledSize(mBackgroundPixmap.size());
10948 QSize scaledSize(mBackgroundPixmap.size());
10957 scaledSize.scale(mViewport.size(), mBackgroundScaledMode);
10949 scaledSize.scale(mViewport.size(), mBackgroundScaledMode);
10958 if (mScaledBackgroundPixmap.size() != scaledSize)
10950 if (mScaledBackgroundPixmap.size() != scaledSize)
10959 mScaledBackgroundPixmap = mBackgroundPixmap.scaled(mViewport.size(), mBackgroundScaledMode, Qt::SmoothTransformation);
10951 mScaledBackgroundPixmap = mBackgroundPixmap.scaled(mViewport.size(), mBackgroundScaledMode, Qt::SmoothTransformation);
10960 painter->drawPixmap(mViewport.topLeft(), mScaledBackgroundPixmap, QRect(0, 0, mViewport.width(), mViewport.height()) & mScaledBackgroundPixmap.rect());
10952 painter->drawPixmap(mViewport.topLeft(), mScaledBackgroundPixmap, QRect(0, 0, mViewport.width(), mViewport.height()) & mScaledBackgroundPixmap.rect());
10961 } else
10953 } else
10962 {
10954 {
10963 painter->drawPixmap(mViewport.topLeft(), mBackgroundPixmap, QRect(0, 0, mViewport.width(), mViewport.height()));
10955 painter->drawPixmap(mViewport.topLeft(), mBackgroundPixmap, QRect(0, 0, mViewport.width(), mViewport.height()));
10964 }
10956 }
10965 }
10957 }
10966 }
10958 }
@@ -10973,16 +10965,16 void QCustomPlot::drawBackground(QCPPain
10973 */
10965 */
10974 void QCustomPlot::axisRemoved(QCPAxis *axis)
10966 void QCustomPlot::axisRemoved(QCPAxis *axis)
10975 {
10967 {
10976 if (xAxis == axis)
10968 if (xAxis == axis)
10977 xAxis = 0;
10969 xAxis = 0;
10978 if (xAxis2 == axis)
10970 if (xAxis2 == axis)
10979 xAxis2 = 0;
10971 xAxis2 = 0;
10980 if (yAxis == axis)
10972 if (yAxis == axis)
10981 yAxis = 0;
10973 yAxis = 0;
10982 if (yAxis2 == axis)
10974 if (yAxis2 == axis)
10983 yAxis2 = 0;
10975 yAxis2 = 0;
10984
10976
10985 // Note: No need to take care of range drag axes and range zoom axes, because they are stored in smart pointers
10977 // Note: No need to take care of range drag axes and range zoom axes, because they are stored in smart pointers
10986 }
10978 }
10987
10979
10988 /*! \internal
10980 /*! \internal
@@ -10992,8 +10984,8 void QCustomPlot::axisRemoved(QCPAxis *a
10992 */
10984 */
10993 void QCustomPlot::legendRemoved(QCPLegend *legend)
10985 void QCustomPlot::legendRemoved(QCPLegend *legend)
10994 {
10986 {
10995 if (this->legend == legend)
10987 if (this->legend == legend)
10996 this->legend = 0;
10988 this->legend = 0;
10997 }
10989 }
10998
10990
10999 /*! \internal
10991 /*! \internal
@@ -11004,8 +10996,8 void QCustomPlot::legendRemoved(QCPLegen
11004 */
10996 */
11005 void QCustomPlot::updateLayerIndices() const
10997 void QCustomPlot::updateLayerIndices() const
11006 {
10998 {
11007 for (int i=0; i<mLayers.size(); ++i)
10999 for (int i=0; i<mLayers.size(); ++i)
11008 mLayers.at(i)->mIndex = i;
11000 mLayers.at(i)->mIndex = i;
11009 }
11001 }
11010
11002
11011 /*! \internal
11003 /*! \internal
@@ -11022,28 +11014,28 void QCustomPlot::updateLayerIndices() c
11022 */
11014 */
11023 QCPLayerable *QCustomPlot::layerableAt(const QPointF &pos, bool onlySelectable, QVariant *selectionDetails) const
11015 QCPLayerable *QCustomPlot::layerableAt(const QPointF &pos, bool onlySelectable, QVariant *selectionDetails) const
11024 {
11016 {
11025 for (int layerIndex=mLayers.size()-1; layerIndex>=0; --layerIndex)
11017 for (int layerIndex=mLayers.size()-1; layerIndex>=0; --layerIndex)
11026 {
11018 {
11027 const QList<QCPLayerable*> layerables = mLayers.at(layerIndex)->children();
11019 const QList<QCPLayerable*> layerables = mLayers.at(layerIndex)->children();
11028 double minimumDistance = selectionTolerance()*1.1;
11020 double minimumDistance = selectionTolerance()*1.1;
11029 QCPLayerable *minimumDistanceLayerable = 0;
11021 QCPLayerable *minimumDistanceLayerable = 0;
11030 for (int i=layerables.size()-1; i>=0; --i)
11022 for (int i=layerables.size()-1; i>=0; --i)
11031 {
11023 {
11032 if (!layerables.at(i)->realVisibility())
11024 if (!layerables.at(i)->realVisibility())
11033 continue;
11025 continue;
11034 QVariant details;
11026 QVariant details;
11035 double dist = layerables.at(i)->selectTest(pos, onlySelectable, &details);
11027 double dist = layerables.at(i)->selectTest(pos, onlySelectable, &details);
11036 if (dist >= 0 && dist < minimumDistance)
11028 if (dist >= 0 && dist < minimumDistance)
11037 {
11029 {
11038 minimumDistance = dist;
11030 minimumDistance = dist;
11039 minimumDistanceLayerable = layerables.at(i);
11031 minimumDistanceLayerable = layerables.at(i);
11040 if (selectionDetails) *selectionDetails = details;
11032 if (selectionDetails) *selectionDetails = details;
11041 }
11033 }
11042 }
11034 }
11043 if (minimumDistance < selectionTolerance())
11035 if (minimumDistance < selectionTolerance())
11044 return minimumDistanceLayerable;
11036 return minimumDistanceLayerable;
11045 }
11037 }
11046 return 0;
11038 return 0;
11047 }
11039 }
11048
11040
11049 /*!
11041 /*!
@@ -11059,11 +11051,11 QCPLayerable *QCustomPlot::layerableAt(c
11059 */
11051 */
11060 bool QCustomPlot::saveRastered(const QString &fileName, int width, int height, double scale, const char *format, int quality)
11052 bool QCustomPlot::saveRastered(const QString &fileName, int width, int height, double scale, const char *format, int quality)
11061 {
11053 {
11062 QPixmap buffer = toPixmap(width, height, scale);
11054 QPixmap buffer = toPixmap(width, height, scale);
11063 if (!buffer.isNull())
11055 if (!buffer.isNull())
11064 return buffer.save(fileName, format, quality);
11056 return buffer.save(fileName, format, quality);
11065 else
11057 else
11066 return false;
11058 return false;
11067 }
11059 }
11068
11060
11069 /*!
11061 /*!
@@ -11076,46 +11068,46 bool QCustomPlot::saveRastered(const QSt
11076 */
11068 */
11077 QPixmap QCustomPlot::toPixmap(int width, int height, double scale)
11069 QPixmap QCustomPlot::toPixmap(int width, int height, double scale)
11078 {
11070 {
11079 // this method is somewhat similar to toPainter. Change something here, and a change in toPainter might be necessary, too.
11071 // this method is somewhat similar to toPainter. Change something here, and a change in toPainter might be necessary, too.
11080 int newWidth, newHeight;
11072 int newWidth, newHeight;
11081 if (width == 0 || height == 0)
11073 if (width == 0 || height == 0)
11082 {
11074 {
11083 newWidth = this->width();
11075 newWidth = this->width();
11084 newHeight = this->height();
11076 newHeight = this->height();
11085 } else
11077 } else
11086 {
11078 {
11087 newWidth = width;
11079 newWidth = width;
11088 newHeight = height;
11080 newHeight = height;
11089 }
11081 }
11090 int scaledWidth = qRound(scale*newWidth);
11082 int scaledWidth = qRound(scale*newWidth);
11091 int scaledHeight = qRound(scale*newHeight);
11083 int scaledHeight = qRound(scale*newHeight);
11092
11084
11093 QPixmap result(scaledWidth, scaledHeight);
11085 QPixmap result(scaledWidth, scaledHeight);
11094 result.fill(mBackgroundBrush.style() == Qt::SolidPattern ? mBackgroundBrush.color() : Qt::transparent); // if using non-solid pattern, make transparent now and draw brush pattern later
11086 result.fill(mBackgroundBrush.style() == Qt::SolidPattern ? mBackgroundBrush.color() : Qt::transparent); // if using non-solid pattern, make transparent now and draw brush pattern later
11095 QCPPainter painter;
11087 QCPPainter painter;
11096 painter.begin(&result);
11088 painter.begin(&result);
11097 if (painter.isActive())
11089 if (painter.isActive())
11098 {
11090 {
11099 QRect oldViewport = viewport();
11091 QRect oldViewport = viewport();
11100 setViewport(QRect(0, 0, newWidth, newHeight));
11092 setViewport(QRect(0, 0, newWidth, newHeight));
11101 painter.setMode(QCPPainter::pmNoCaching);
11093 painter.setMode(QCPPainter::pmNoCaching);
11102 if (!qFuzzyCompare(scale, 1.0))
11094 if (!qFuzzyCompare(scale, 1.0))
11103 {
11095 {
11104 if (scale > 1.0) // for scale < 1 we always want cosmetic pens where possible, because else lines might disappear for very small scales
11096 if (scale > 1.0) // for scale < 1 we always want cosmetic pens where possible, because else lines might disappear for very small scales
11105 painter.setMode(QCPPainter::pmNonCosmetic);
11097 painter.setMode(QCPPainter::pmNonCosmetic);
11106 painter.scale(scale, scale);
11098 painter.scale(scale, scale);
11107 }
11099 }
11108 if (mBackgroundBrush.style() != Qt::SolidPattern && mBackgroundBrush.style() != Qt::NoBrush)
11100 if (mBackgroundBrush.style() != Qt::SolidPattern && mBackgroundBrush.style() != Qt::NoBrush)
11109 painter.fillRect(mViewport, mBackgroundBrush);
11101 painter.fillRect(mViewport, mBackgroundBrush);
11110 draw(&painter);
11102 draw(&painter);
11111 setViewport(oldViewport);
11103 setViewport(oldViewport);
11112 painter.end();
11104 painter.end();
11113 } else // might happen if pixmap has width or height zero
11105 } else // might happen if pixmap has width or height zero
11114 {
11106 {
11115 qDebug() << Q_FUNC_INFO << "Couldn't activate painter on pixmap";
11107 qDebug() << Q_FUNC_INFO << "Couldn't activate painter on pixmap";
11116 return QPixmap();
11108 return QPixmap();
11117 }
11109 }
11118 return result;
11110 return result;
11119 }
11111 }
11120
11112
11121 /*!
11113 /*!
@@ -11132,31 +11124,31 QPixmap QCustomPlot::toPixmap(int width,
11132 */
11124 */
11133 void QCustomPlot::toPainter(QCPPainter *painter, int width, int height)
11125 void QCustomPlot::toPainter(QCPPainter *painter, int width, int height)
11134 {
11126 {
11135 // this method is somewhat similar to toPixmap. Change something here, and a change in toPixmap might be necessary, too.
11127 // this method is somewhat similar to toPixmap. Change something here, and a change in toPixmap might be necessary, too.
11136 int newWidth, newHeight;
11128 int newWidth, newHeight;
11137 if (width == 0 || height == 0)
11129 if (width == 0 || height == 0)
11138 {
11130 {
11139 newWidth = this->width();
11131 newWidth = this->width();
11140 newHeight = this->height();
11132 newHeight = this->height();
11141 } else
11133 } else
11142 {
11134 {
11143 newWidth = width;
11135 newWidth = width;
11144 newHeight = height;
11136 newHeight = height;
11145 }
11137 }
11146
11138
11147 if (painter->isActive())
11139 if (painter->isActive())
11148 {
11140 {
11149 QRect oldViewport = viewport();
11141 QRect oldViewport = viewport();
11150 setViewport(QRect(0, 0, newWidth, newHeight));
11142 setViewport(QRect(0, 0, newWidth, newHeight));
11151 painter->setMode(QCPPainter::pmNoCaching);
11143 painter->setMode(QCPPainter::pmNoCaching);
11152 // warning: the following is different in toPixmap, because a solid background color is applied there via QPixmap::fill
11144 // warning: the following is different in toPixmap, because a solid background color is applied there via QPixmap::fill
11153 // here, we need to do this via QPainter::fillRect.
11145 // here, we need to do this via QPainter::fillRect.
11154 if (mBackgroundBrush.style() != Qt::NoBrush)
11146 if (mBackgroundBrush.style() != Qt::NoBrush)
11155 painter->fillRect(mViewport, mBackgroundBrush);
11147 painter->fillRect(mViewport, mBackgroundBrush);
11156 draw(painter);
11148 draw(painter);
11157 setViewport(oldViewport);
11149 setViewport(oldViewport);
11158 } else
11150 } else
11159 qDebug() << Q_FUNC_INFO << "Passed painter is not active";
11151 qDebug() << Q_FUNC_INFO << "Passed painter is not active";
11160 }
11152 }
11161
11153
11162
11154
@@ -11197,22 +11189,22 void QCustomPlot::toPainter(QCPPainter *
11197 The color level count is initialized to 350.
11189 The color level count is initialized to 350.
11198 */
11190 */
11199 QCPColorGradient::QCPColorGradient(GradientPreset preset) :
11191 QCPColorGradient::QCPColorGradient(GradientPreset preset) :
11200 mLevelCount(350),
11192 mLevelCount(350),
11201 mColorInterpolation(ciRGB),
11193 mColorInterpolation(ciRGB),
11202 mPeriodic(false),
11194 mPeriodic(false),
11203 mColorBufferInvalidated(true)
11195 mColorBufferInvalidated(true)
11204 {
11196 {
11205 mColorBuffer.fill(qRgb(0, 0, 0), mLevelCount);
11197 mColorBuffer.fill(qRgb(0, 0, 0), mLevelCount);
11206 loadPreset(preset);
11198 loadPreset(preset);
11207 }
11199 }
11208
11200
11209 /* undocumented operator */
11201 /* undocumented operator */
11210 bool QCPColorGradient::operator==(const QCPColorGradient &other) const
11202 bool QCPColorGradient::operator==(const QCPColorGradient &other) const
11211 {
11203 {
11212 return ((other.mLevelCount == this->mLevelCount) &&
11204 return ((other.mLevelCount == this->mLevelCount) &&
11213 (other.mColorInterpolation == this->mColorInterpolation) &&
11205 (other.mColorInterpolation == this->mColorInterpolation) &&
11214 (other.mPeriodic == this->mPeriodic) &&
11206 (other.mPeriodic == this->mPeriodic) &&
11215 (other.mColorStops == this->mColorStops));
11207 (other.mColorStops == this->mColorStops));
11216 }
11208 }
11217
11209
11218 /*!
11210 /*!
@@ -11223,15 +11215,15 bool QCPColorGradient::operator==(const
11223 */
11215 */
11224 void QCPColorGradient::setLevelCount(int n)
11216 void QCPColorGradient::setLevelCount(int n)
11225 {
11217 {
11226 if (n < 2)
11218 if (n < 2)
11227 {
11219 {
11228 qDebug() << Q_FUNC_INFO << "n must be greater or equal 2 but was" << n;
11220 qDebug() << Q_FUNC_INFO << "n must be greater or equal 2 but was" << n;
11229 n = 2;
11221 n = 2;
11230 }
11222 }
11231 if (n != mLevelCount)
11223 if (n != mLevelCount)
11232 {
11224 {
11233 mLevelCount = n;
11225 mLevelCount = n;
11234 mColorBufferInvalidated = true;
11226 mColorBufferInvalidated = true;
11235 }
11227 }
11236 }
11228 }
11237
11229
@@ -11247,8 +11239,8 void QCPColorGradient::setLevelCount(int
11247 */
11239 */
11248 void QCPColorGradient::setColorStops(const QMap<double, QColor> &colorStops)
11240 void QCPColorGradient::setColorStops(const QMap<double, QColor> &colorStops)
11249 {
11241 {
11250 mColorStops = colorStops;
11242 mColorStops = colorStops;
11251 mColorBufferInvalidated = true;
11243 mColorBufferInvalidated = true;
11252 }
11244 }
11253
11245
11254 /*!
11246 /*!
@@ -11259,8 +11251,8 void QCPColorGradient::setColorStops(con
11259 */
11251 */
11260 void QCPColorGradient::setColorStopAt(double position, const QColor &color)
11252 void QCPColorGradient::setColorStopAt(double position, const QColor &color)
11261 {
11253 {
11262 mColorStops.insert(position, color);
11254 mColorStops.insert(position, color);
11263 mColorBufferInvalidated = true;
11255 mColorBufferInvalidated = true;
11264 }
11256 }
11265
11257
11266 /*!
11258 /*!
@@ -11272,10 +11264,10 void QCPColorGradient::setColorStopAt(do
11272 */
11264 */
11273 void QCPColorGradient::setColorInterpolation(QCPColorGradient::ColorInterpolation interpolation)
11265 void QCPColorGradient::setColorInterpolation(QCPColorGradient::ColorInterpolation interpolation)
11274 {
11266 {
11275 if (interpolation != mColorInterpolation)
11267 if (interpolation != mColorInterpolation)
11276 {
11268 {
11277 mColorInterpolation = interpolation;
11269 mColorInterpolation = interpolation;
11278 mColorBufferInvalidated = true;
11270 mColorBufferInvalidated = true;
11279 }
11271 }
11280 }
11272 }
11281
11273
@@ -11296,7 +11288,7 void QCPColorGradient::setColorInterpola
11296 */
11288 */
11297 void QCPColorGradient::setPeriodic(bool enabled)
11289 void QCPColorGradient::setPeriodic(bool enabled)
11298 {
11290 {
11299 mPeriodic = enabled;
11291 mPeriodic = enabled;
11300 }
11292 }
11301
11293
11302 /*!
11294 /*!
@@ -11313,65 +11305,65 void QCPColorGradient::setPeriodic(bool
11313 */
11305 */
11314 void QCPColorGradient::colorize(const double *data, const QCPRange &range, QRgb *scanLine, int n, int dataIndexFactor, bool logarithmic)
11306 void QCPColorGradient::colorize(const double *data, const QCPRange &range, QRgb *scanLine, int n, int dataIndexFactor, bool logarithmic)
11315 {
11307 {
11316 // If you change something here, make sure to also adapt ::color()
11308 // If you change something here, make sure to also adapt ::color()
11317 if (!data)
11309 if (!data)
11318 {
11310 {
11319 qDebug() << Q_FUNC_INFO << "null pointer given as data";
11311 qDebug() << Q_FUNC_INFO << "null pointer given as data";
11320 return;
11312 return;
11321 }
11313 }
11322 if (!scanLine)
11314 if (!scanLine)
11323 {
11315 {
11324 qDebug() << Q_FUNC_INFO << "null pointer given as scanLine";
11316 qDebug() << Q_FUNC_INFO << "null pointer given as scanLine";
11325 return;
11317 return;
11326 }
11318 }
11327 if (mColorBufferInvalidated)
11319 if (mColorBufferInvalidated)
11328 updateColorBuffer();
11320 updateColorBuffer();
11329
11321
11330 if (!logarithmic)
11322 if (!logarithmic)
11331 {
11323 {
11332 const double posToIndexFactor = (mLevelCount-1)/range.size();
11324 const double posToIndexFactor = (mLevelCount-1)/range.size();
11333 if (mPeriodic)
11325 if (mPeriodic)
11334 {
11326 {
11335 for (int i=0; i<n; ++i)
11327 for (int i=0; i<n; ++i)
11336 {
11328 {
11337 int index = (int)((data[dataIndexFactor*i]-range.lower)*posToIndexFactor) % mLevelCount;
11329 int index = (int)((data[dataIndexFactor*i]-range.lower)*posToIndexFactor) % mLevelCount;
11338 if (index < 0)
11330 if (index < 0)
11339 index += mLevelCount;
11331 index += mLevelCount;
11340 scanLine[i] = mColorBuffer.at(index);
11332 scanLine[i] = mColorBuffer.at(index);
11341 }
11333 }
11342 } else
11334 } else
11343 {
11335 {
11344 for (int i=0; i<n; ++i)
11336 for (int i=0; i<n; ++i)
11345 {
11337 {
11346 int index = (data[dataIndexFactor*i]-range.lower)*posToIndexFactor;
11338 int index = (data[dataIndexFactor*i]-range.lower)*posToIndexFactor;
11347 if (index < 0)
11339 if (index < 0)
11348 index = 0;
11340 index = 0;
11349 else if (index >= mLevelCount)
11341 else if (index >= mLevelCount)
11350 index = mLevelCount-1;
11342 index = mLevelCount-1;
11351 scanLine[i] = mColorBuffer.at(index);
11343 scanLine[i] = mColorBuffer.at(index);
11352 }
11344 }
11353 }
11345 }
11354 } else // logarithmic == true
11346 } else // logarithmic == true
11355 {
11347 {
11356 if (mPeriodic)
11348 if (mPeriodic)
11357 {
11349 {
11358 for (int i=0; i<n; ++i)
11350 for (int i=0; i<n; ++i)
11359 {
11351 {
11360 int index = (int)(qLn(data[dataIndexFactor*i]/range.lower)/qLn(range.upper/range.lower)*(mLevelCount-1)) % mLevelCount;
11352 int index = (int)(qLn(data[dataIndexFactor*i]/range.lower)/qLn(range.upper/range.lower)*(mLevelCount-1)) % mLevelCount;
11361 if (index < 0)
11353 if (index < 0)
11362 index += mLevelCount;
11354 index += mLevelCount;
11363 scanLine[i] = mColorBuffer.at(index);
11355 scanLine[i] = mColorBuffer.at(index);
11364 }
11356 }
11365 } else
11357 } else
11366 {
11358 {
11367 for (int i=0; i<n; ++i)
11359 for (int i=0; i<n; ++i)
11368 {
11360 {
11369 int index = qLn(data[dataIndexFactor*i]/range.lower)/qLn(range.upper/range.lower)*(mLevelCount-1);
11361 int index = qLn(data[dataIndexFactor*i]/range.lower)/qLn(range.upper/range.lower)*(mLevelCount-1);
11370 if (index < 0)
11362 if (index < 0)
11371 index = 0;
11363 index = 0;
11372 else if (index >= mLevelCount)
11364 else if (index >= mLevelCount)
11373 index = mLevelCount-1;
11365 index = mLevelCount-1;
11374 scanLine[i] = mColorBuffer.at(index);
11366 scanLine[i] = mColorBuffer.at(index);
11375 }
11367 }
11376 }
11368 }
11377 }
11369 }
@@ -11388,27 +11380,27 void QCPColorGradient::colorize(const do
11388 */
11380 */
11389 QRgb QCPColorGradient::color(double position, const QCPRange &range, bool logarithmic)
11381 QRgb QCPColorGradient::color(double position, const QCPRange &range, bool logarithmic)
11390 {
11382 {
11391 // If you change something here, make sure to also adapt ::colorize()
11383 // If you change something here, make sure to also adapt ::colorize()
11392 if (mColorBufferInvalidated)
11384 if (mColorBufferInvalidated)
11393 updateColorBuffer();
11385 updateColorBuffer();
11394 int index = 0;
11386 int index = 0;
11395 if (!logarithmic)
11387 if (!logarithmic)
11396 index = (position-range.lower)*(mLevelCount-1)/range.size();
11388 index = (position-range.lower)*(mLevelCount-1)/range.size();
11397 else
11389 else
11398 index = qLn(position/range.lower)/qLn(range.upper/range.lower)*(mLevelCount-1);
11390 index = qLn(position/range.lower)/qLn(range.upper/range.lower)*(mLevelCount-1);
11399 if (mPeriodic)
11391 if (mPeriodic)
11400 {
11392 {
11401 index = index % mLevelCount;
11393 index = index % mLevelCount;
11402 if (index < 0)
11394 if (index < 0)
11403 index += mLevelCount;
11395 index += mLevelCount;
11404 } else
11396 } else
11405 {
11397 {
11406 if (index < 0)
11398 if (index < 0)
11407 index = 0;
11399 index = 0;
11408 else if (index >= mLevelCount)
11400 else if (index >= mLevelCount)
11409 index = mLevelCount-1;
11401 index = mLevelCount-1;
11410 }
11402 }
11411 return mColorBuffer.at(index);
11403 return mColorBuffer.at(index);
11412 }
11404 }
11413
11405
11414 /*!
11406 /*!
@@ -11420,105 +11412,105 QRgb QCPColorGradient::color(double posi
11420 */
11412 */
11421 void QCPColorGradient::loadPreset(GradientPreset preset)
11413 void QCPColorGradient::loadPreset(GradientPreset preset)
11422 {
11414 {
11423 clearColorStops();
11415 clearColorStops();
11424 switch (preset)
11416 switch (preset)
11425 {
11417 {
11426 case gpGrayscale:
11418 case gpGrayscale:
11427 setColorInterpolation(ciRGB);
11419 setColorInterpolation(ciRGB);
11428 setColorStopAt(0, Qt::black);
11420 setColorStopAt(0, Qt::black);
11429 setColorStopAt(1, Qt::white);
11421 setColorStopAt(1, Qt::white);
11430 break;
11422 break;
11431 case gpHot:
11423 case gpHot:
11432 setColorInterpolation(ciRGB);
11424 setColorInterpolation(ciRGB);
11433 setColorStopAt(0, QColor(50, 0, 0));
11425 setColorStopAt(0, QColor(50, 0, 0));
11434 setColorStopAt(0.2, QColor(180, 10, 0));
11426 setColorStopAt(0.2, QColor(180, 10, 0));
11435 setColorStopAt(0.4, QColor(245, 50, 0));
11427 setColorStopAt(0.4, QColor(245, 50, 0));
11436 setColorStopAt(0.6, QColor(255, 150, 10));
11428 setColorStopAt(0.6, QColor(255, 150, 10));
11437 setColorStopAt(0.8, QColor(255, 255, 50));
11429 setColorStopAt(0.8, QColor(255, 255, 50));
11438 setColorStopAt(1, QColor(255, 255, 255));
11430 setColorStopAt(1, QColor(255, 255, 255));
11439 break;
11431 break;
11440 case gpCold:
11432 case gpCold:
11441 setColorInterpolation(ciRGB);
11433 setColorInterpolation(ciRGB);
11442 setColorStopAt(0, QColor(0, 0, 50));
11434 setColorStopAt(0, QColor(0, 0, 50));
11443 setColorStopAt(0.2, QColor(0, 10, 180));
11435 setColorStopAt(0.2, QColor(0, 10, 180));
11444 setColorStopAt(0.4, QColor(0, 50, 245));
11436 setColorStopAt(0.4, QColor(0, 50, 245));
11445 setColorStopAt(0.6, QColor(10, 150, 255));
11437 setColorStopAt(0.6, QColor(10, 150, 255));
11446 setColorStopAt(0.8, QColor(50, 255, 255));
11438 setColorStopAt(0.8, QColor(50, 255, 255));
11447 setColorStopAt(1, QColor(255, 255, 255));
11439 setColorStopAt(1, QColor(255, 255, 255));
11448 break;
11440 break;
11449 case gpNight:
11441 case gpNight:
11450 setColorInterpolation(ciHSV);
11442 setColorInterpolation(ciHSV);
11451 setColorStopAt(0, QColor(10, 20, 30));
11443 setColorStopAt(0, QColor(10, 20, 30));
11452 setColorStopAt(1, QColor(250, 255, 250));
11444 setColorStopAt(1, QColor(250, 255, 250));
11453 break;
11445 break;
11454 case gpCandy:
11446 case gpCandy:
11455 setColorInterpolation(ciHSV);
11447 setColorInterpolation(ciHSV);
11456 setColorStopAt(0, QColor(0, 0, 255));
11448 setColorStopAt(0, QColor(0, 0, 255));
11457 setColorStopAt(1, QColor(255, 250, 250));
11449 setColorStopAt(1, QColor(255, 250, 250));
11458 break;
11450 break;
11459 case gpGeography:
11451 case gpGeography:
11460 setColorInterpolation(ciRGB);
11452 setColorInterpolation(ciRGB);
11461 setColorStopAt(0, QColor(70, 170, 210));
11453 setColorStopAt(0, QColor(70, 170, 210));
11462 setColorStopAt(0.20, QColor(90, 160, 180));
11454 setColorStopAt(0.20, QColor(90, 160, 180));
11463 setColorStopAt(0.25, QColor(45, 130, 175));
11455 setColorStopAt(0.25, QColor(45, 130, 175));
11464 setColorStopAt(0.30, QColor(100, 140, 125));
11456 setColorStopAt(0.30, QColor(100, 140, 125));
11465 setColorStopAt(0.5, QColor(100, 140, 100));
11457 setColorStopAt(0.5, QColor(100, 140, 100));
11466 setColorStopAt(0.6, QColor(130, 145, 120));
11458 setColorStopAt(0.6, QColor(130, 145, 120));
11467 setColorStopAt(0.7, QColor(140, 130, 120));
11459 setColorStopAt(0.7, QColor(140, 130, 120));
11468 setColorStopAt(0.9, QColor(180, 190, 190));
11460 setColorStopAt(0.9, QColor(180, 190, 190));
11469 setColorStopAt(1, QColor(210, 210, 230));
11461 setColorStopAt(1, QColor(210, 210, 230));
11470 break;
11462 break;
11471 case gpIon:
11463 case gpIon:
11472 setColorInterpolation(ciHSV);
11464 setColorInterpolation(ciHSV);
11473 setColorStopAt(0, QColor(50, 10, 10));
11465 setColorStopAt(0, QColor(50, 10, 10));
11474 setColorStopAt(0.45, QColor(0, 0, 255));
11466 setColorStopAt(0.45, QColor(0, 0, 255));
11475 setColorStopAt(0.8, QColor(0, 255, 255));
11467 setColorStopAt(0.8, QColor(0, 255, 255));
11476 setColorStopAt(1, QColor(0, 255, 0));
11468 setColorStopAt(1, QColor(0, 255, 0));
11477 break;
11469 break;
11478 case gpThermal:
11470 case gpThermal:
11479 setColorInterpolation(ciRGB);
11471 setColorInterpolation(ciRGB);
11480 setColorStopAt(0, QColor(0, 0, 50));
11472 setColorStopAt(0, QColor(0, 0, 50));
11481 setColorStopAt(0.15, QColor(20, 0, 120));
11473 setColorStopAt(0.15, QColor(20, 0, 120));
11482 setColorStopAt(0.33, QColor(200, 30, 140));
11474 setColorStopAt(0.33, QColor(200, 30, 140));
11483 setColorStopAt(0.6, QColor(255, 100, 0));
11475 setColorStopAt(0.6, QColor(255, 100, 0));
11484 setColorStopAt(0.85, QColor(255, 255, 40));
11476 setColorStopAt(0.85, QColor(255, 255, 40));
11485 setColorStopAt(1, QColor(255, 255, 255));
11477 setColorStopAt(1, QColor(255, 255, 255));
11486 break;
11478 break;
11487 case gpPolar:
11479 case gpPolar:
11488 setColorInterpolation(ciRGB);
11480 setColorInterpolation(ciRGB);
11489 setColorStopAt(0, QColor(50, 255, 255));
11481 setColorStopAt(0, QColor(50, 255, 255));
11490 setColorStopAt(0.18, QColor(10, 70, 255));
11482 setColorStopAt(0.18, QColor(10, 70, 255));
11491 setColorStopAt(0.28, QColor(10, 10, 190));
11483 setColorStopAt(0.28, QColor(10, 10, 190));
11492 setColorStopAt(0.5, QColor(0, 0, 0));
11484 setColorStopAt(0.5, QColor(0, 0, 0));
11493 setColorStopAt(0.72, QColor(190, 10, 10));
11485 setColorStopAt(0.72, QColor(190, 10, 10));
11494 setColorStopAt(0.82, QColor(255, 70, 10));
11486 setColorStopAt(0.82, QColor(255, 70, 10));
11495 setColorStopAt(1, QColor(255, 255, 50));
11487 setColorStopAt(1, QColor(255, 255, 50));
11496 break;
11488 break;
11497 case gpSpectrum:
11489 case gpSpectrum:
11498 setColorInterpolation(ciHSV);
11490 setColorInterpolation(ciHSV);
11499 setColorStopAt(0, QColor(50, 0, 50));
11491 setColorStopAt(0, QColor(50, 0, 50));
11500 setColorStopAt(0.15, QColor(0, 0, 255));
11492 setColorStopAt(0.15, QColor(0, 0, 255));
11501 setColorStopAt(0.35, QColor(0, 255, 255));
11493 setColorStopAt(0.35, QColor(0, 255, 255));
11502 setColorStopAt(0.6, QColor(255, 255, 0));
11494 setColorStopAt(0.6, QColor(255, 255, 0));
11503 setColorStopAt(0.75, QColor(255, 30, 0));
11495 setColorStopAt(0.75, QColor(255, 30, 0));
11504 setColorStopAt(1, QColor(50, 0, 0));
11496 setColorStopAt(1, QColor(50, 0, 0));
11505 break;
11497 break;
11506 case gpJet:
11498 case gpJet:
11507 setColorInterpolation(ciRGB);
11499 setColorInterpolation(ciRGB);
11508 setColorStopAt(0, QColor(0, 0, 100));
11500 setColorStopAt(0, QColor(0, 0, 100));
11509 setColorStopAt(0.15, QColor(0, 50, 255));
11501 setColorStopAt(0.15, QColor(0, 50, 255));
11510 setColorStopAt(0.35, QColor(0, 255, 255));
11502 setColorStopAt(0.35, QColor(0, 255, 255));
11511 setColorStopAt(0.65, QColor(255, 255, 0));
11503 setColorStopAt(0.65, QColor(255, 255, 0));
11512 setColorStopAt(0.85, QColor(255, 30, 0));
11504 setColorStopAt(0.85, QColor(255, 30, 0));
11513 setColorStopAt(1, QColor(100, 0, 0));
11505 setColorStopAt(1, QColor(100, 0, 0));
11514 break;
11506 break;
11515 case gpHues:
11507 case gpHues:
11516 setColorInterpolation(ciHSV);
11508 setColorInterpolation(ciHSV);
11517 setColorStopAt(0, QColor(255, 0, 0));
11509 setColorStopAt(0, QColor(255, 0, 0));
11518 setColorStopAt(1.0/3.0, QColor(0, 0, 255));
11510 setColorStopAt(1.0/3.0, QColor(0, 0, 255));
11519 setColorStopAt(2.0/3.0, QColor(0, 255, 0));
11511 setColorStopAt(2.0/3.0, QColor(0, 255, 0));
11520 setColorStopAt(1, QColor(255, 0, 0));
11512 setColorStopAt(1, QColor(255, 0, 0));
11521 break;
11513 break;
11522 }
11514 }
11523 }
11515 }
11524
11516
@@ -11529,8 +11521,8 void QCPColorGradient::loadPreset(Gradie
11529 */
11521 */
11530 void QCPColorGradient::clearColorStops()
11522 void QCPColorGradient::clearColorStops()
11531 {
11523 {
11532 mColorStops.clear();
11524 mColorStops.clear();
11533 mColorBufferInvalidated = true;
11525 mColorBufferInvalidated = true;
11534 }
11526 }
11535
11527
11536 /*!
11528 /*!
@@ -11541,11 +11533,11 void QCPColorGradient::clearColorStops()
11541 */
11533 */
11542 QCPColorGradient QCPColorGradient::inverted() const
11534 QCPColorGradient QCPColorGradient::inverted() const
11543 {
11535 {
11544 QCPColorGradient result(*this);
11536 QCPColorGradient result(*this);
11545 result.clearColorStops();
11537 result.clearColorStops();
11546 for (QMap<double, QColor>::const_iterator it=mColorStops.constBegin(); it!=mColorStops.constEnd(); ++it)
11538 for (QMap<double, QColor>::const_iterator it=mColorStops.constBegin(); it!=mColorStops.constEnd(); ++it)
11547 result.setColorStopAt(1.0-it.key(), it.value());
11539 result.setColorStopAt(1.0-it.key(), it.value());
11548 return result;
11540 return result;
11549 }
11541 }
11550
11542
11551 /*! \internal
11543 /*! \internal
@@ -11555,63 +11547,63 QCPColorGradient QCPColorGradient::inver
11555 */
11547 */
11556 void QCPColorGradient::updateColorBuffer()
11548 void QCPColorGradient::updateColorBuffer()
11557 {
11549 {
11558 if (mColorBuffer.size() != mLevelCount)
11550 if (mColorBuffer.size() != mLevelCount)
11559 mColorBuffer.resize(mLevelCount);
11551 mColorBuffer.resize(mLevelCount);
11560 if (mColorStops.size() > 1)
11552 if (mColorStops.size() > 1)
11561 {
11553 {
11562 double indexToPosFactor = 1.0/(double)(mLevelCount-1);
11554 double indexToPosFactor = 1.0/(double)(mLevelCount-1);
11563 for (int i=0; i<mLevelCount; ++i)
11555 for (int i=0; i<mLevelCount; ++i)
11564 {
11556 {
11565 double position = i*indexToPosFactor;
11557 double position = i*indexToPosFactor;
11566 QMap<double, QColor>::const_iterator it = mColorStops.lowerBound(position);
11558 QMap<double, QColor>::const_iterator it = mColorStops.lowerBound(position);
11567 if (it == mColorStops.constEnd()) // position is on or after last stop, use color of last stop
11559 if (it == mColorStops.constEnd()) // position is on or after last stop, use color of last stop
11568 {
11560 {
11569 mColorBuffer[i] = (it-1).value().rgb();
11561 mColorBuffer[i] = (it-1).value().rgb();
11570 } else if (it == mColorStops.constBegin()) // position is on or before first stop, use color of first stop
11562 } else if (it == mColorStops.constBegin()) // position is on or before first stop, use color of first stop
11571 {
11563 {
11572 mColorBuffer[i] = it.value().rgb();
11564 mColorBuffer[i] = it.value().rgb();
11573 } else // position is in between stops (or on an intermediate stop), interpolate color
11565 } else // position is in between stops (or on an intermediate stop), interpolate color
11574 {
11566 {
11575 QMap<double, QColor>::const_iterator high = it;
11567 QMap<double, QColor>::const_iterator high = it;
11576 QMap<double, QColor>::const_iterator low = it-1;
11568 QMap<double, QColor>::const_iterator low = it-1;
11577 double t = (position-low.key())/(high.key()-low.key()); // interpolation factor 0..1
11569 double t = (position-low.key())/(high.key()-low.key()); // interpolation factor 0..1
11578 switch (mColorInterpolation)
11570 switch (mColorInterpolation)
11579 {
11571 {
11580 case ciRGB:
11572 case ciRGB:
11581 {
11573 {
11582 mColorBuffer[i] = qRgb((1-t)*low.value().red() + t*high.value().red(),
11574 mColorBuffer[i] = qRgb((1-t)*low.value().red() + t*high.value().red(),
11583 (1-t)*low.value().green() + t*high.value().green(),
11575 (1-t)*low.value().green() + t*high.value().green(),
11584 (1-t)*low.value().blue() + t*high.value().blue());
11576 (1-t)*low.value().blue() + t*high.value().blue());
11585 break;
11577 break;
11586 }
11578 }
11587 case ciHSV:
11579 case ciHSV:
11588 {
11580 {
11589 QColor lowHsv = low.value().toHsv();
11581 QColor lowHsv = low.value().toHsv();
11590 QColor highHsv = high.value().toHsv();
11582 QColor highHsv = high.value().toHsv();
11591 double hue = 0;
11583 double hue = 0;
11592 double hueDiff = highHsv.hueF()-lowHsv.hueF();
11584 double hueDiff = highHsv.hueF()-lowHsv.hueF();
11593 if (hueDiff > 0.5)
11585 if (hueDiff > 0.5)
11594 hue = lowHsv.hueF() - t*(1.0-hueDiff);
11586 hue = lowHsv.hueF() - t*(1.0-hueDiff);
11595 else if (hueDiff < -0.5)
11587 else if (hueDiff < -0.5)
11596 hue = lowHsv.hueF() + t*(1.0+hueDiff);
11588 hue = lowHsv.hueF() + t*(1.0+hueDiff);
11597 else
11589 else
11598 hue = lowHsv.hueF() + t*hueDiff;
11590 hue = lowHsv.hueF() + t*hueDiff;
11599 if (hue < 0) hue += 1.0;
11591 if (hue < 0) hue += 1.0;
11600 else if (hue >= 1.0) hue -= 1.0;
11592 else if (hue >= 1.0) hue -= 1.0;
11601 mColorBuffer[i] = QColor::fromHsvF(hue, (1-t)*lowHsv.saturationF() + t*highHsv.saturationF(), (1-t)*lowHsv.valueF() + t*highHsv.valueF()).rgb();
11593 mColorBuffer[i] = QColor::fromHsvF(hue, (1-t)*lowHsv.saturationF() + t*highHsv.saturationF(), (1-t)*lowHsv.valueF() + t*highHsv.valueF()).rgb();
11602 break;
11594 break;
11603 }
11595 }
11604 }
11596 }
11605 }
11597 }
11606 }
11598 }
11607 } else if (mColorStops.size() == 1)
11599 } else if (mColorStops.size() == 1)
11608 {
11600 {
11609 mColorBuffer.fill(mColorStops.constBegin().value().rgb());
11601 mColorBuffer.fill(mColorStops.constBegin().value().rgb());
11610 } else // mColorStops is empty, fill color buffer with black
11602 } else // mColorStops is empty, fill color buffer with black
11611 {
11603 {
11612 mColorBuffer.fill(qRgb(0, 0, 0));
11604 mColorBuffer.fill(qRgb(0, 0, 0));
11613 }
11605 }
11614 mColorBufferInvalidated = false;
11606 mColorBufferInvalidated = false;
11615 }
11607 }
11616
11608
11617
11609
@@ -11745,57 +11737,57 void QCPColorGradient::updateColorBuffer
11745 sides, the top and right axes are set invisible initially.
11737 sides, the top and right axes are set invisible initially.
11746 */
11738 */
11747 QCPAxisRect::QCPAxisRect(QCustomPlot *parentPlot, bool setupDefaultAxes) :
11739 QCPAxisRect::QCPAxisRect(QCustomPlot *parentPlot, bool setupDefaultAxes) :
11748 QCPLayoutElement(parentPlot),
11740 QCPLayoutElement(parentPlot),
11749 mBackgroundBrush(Qt::NoBrush),
11741 mBackgroundBrush(Qt::NoBrush),
11750 mBackgroundScaled(true),
11742 mBackgroundScaled(true),
11751 mBackgroundScaledMode(Qt::KeepAspectRatioByExpanding),
11743 mBackgroundScaledMode(Qt::KeepAspectRatioByExpanding),
11752 mInsetLayout(new QCPLayoutInset),
11744 mInsetLayout(new QCPLayoutInset),
11753 mRangeDrag(Qt::Horizontal|Qt::Vertical),
11745 mRangeDrag(Qt::Horizontal|Qt::Vertical),
11754 mRangeZoom(Qt::Horizontal|Qt::Vertical),
11746 mRangeZoom(Qt::Horizontal|Qt::Vertical),
11755 mRangeZoomFactorHorz(0.85),
11747 mRangeZoomFactorHorz(0.85),
11756 mRangeZoomFactorVert(0.85),
11748 mRangeZoomFactorVert(0.85),
11757 mDragging(false)
11749 mDragging(false)
11758 {
11750 {
11759 mInsetLayout->initializeParentPlot(mParentPlot);
11751 mInsetLayout->initializeParentPlot(mParentPlot);
11760 mInsetLayout->setParentLayerable(this);
11752 mInsetLayout->setParentLayerable(this);
11761 mInsetLayout->setParent(this);
11753 mInsetLayout->setParent(this);
11762
11754
11763 setMinimumSize(50, 50);
11755 setMinimumSize(50, 50);
11764 setMinimumMargins(QMargins(15, 15, 15, 15));
11756 setMinimumMargins(QMargins(15, 15, 15, 15));
11765 mAxes.insert(QCPAxis::atLeft, QList<QCPAxis*>());
11757 mAxes.insert(QCPAxis::atLeft, QList<QCPAxis*>());
11766 mAxes.insert(QCPAxis::atRight, QList<QCPAxis*>());
11758 mAxes.insert(QCPAxis::atRight, QList<QCPAxis*>());
11767 mAxes.insert(QCPAxis::atTop, QList<QCPAxis*>());
11759 mAxes.insert(QCPAxis::atTop, QList<QCPAxis*>());
11768 mAxes.insert(QCPAxis::atBottom, QList<QCPAxis*>());
11760 mAxes.insert(QCPAxis::atBottom, QList<QCPAxis*>());
11769
11761
11770 if (setupDefaultAxes)
11762 if (setupDefaultAxes)
11771 {
11763 {
11772 QCPAxis *xAxis = addAxis(QCPAxis::atBottom);
11764 QCPAxis *xAxis = addAxis(QCPAxis::atBottom);
11773 QCPAxis *yAxis = addAxis(QCPAxis::atLeft);
11765 QCPAxis *yAxis = addAxis(QCPAxis::atLeft);
11774 QCPAxis *xAxis2 = addAxis(QCPAxis::atTop);
11766 QCPAxis *xAxis2 = addAxis(QCPAxis::atTop);
11775 QCPAxis *yAxis2 = addAxis(QCPAxis::atRight);
11767 QCPAxis *yAxis2 = addAxis(QCPAxis::atRight);
11776 setRangeDragAxes(xAxis, yAxis);
11768 setRangeDragAxes(xAxis, yAxis);
11777 setRangeZoomAxes(xAxis, yAxis);
11769 setRangeZoomAxes(xAxis, yAxis);
11778 xAxis2->setVisible(false);
11770 xAxis2->setVisible(false);
11779 yAxis2->setVisible(false);
11771 yAxis2->setVisible(false);
11780 xAxis->grid()->setVisible(true);
11772 xAxis->grid()->setVisible(true);
11781 yAxis->grid()->setVisible(true);
11773 yAxis->grid()->setVisible(true);
11782 xAxis2->grid()->setVisible(false);
11774 xAxis2->grid()->setVisible(false);
11783 yAxis2->grid()->setVisible(false);
11775 yAxis2->grid()->setVisible(false);
11784 xAxis2->grid()->setZeroLinePen(Qt::NoPen);
11776 xAxis2->grid()->setZeroLinePen(Qt::NoPen);
11785 yAxis2->grid()->setZeroLinePen(Qt::NoPen);
11777 yAxis2->grid()->setZeroLinePen(Qt::NoPen);
11786 xAxis2->grid()->setVisible(false);
11778 xAxis2->grid()->setVisible(false);
11787 yAxis2->grid()->setVisible(false);
11779 yAxis2->grid()->setVisible(false);
11788 }
11780 }
11789 }
11781 }
11790
11782
11791 QCPAxisRect::~QCPAxisRect()
11783 QCPAxisRect::~QCPAxisRect()
11792 {
11784 {
11793 delete mInsetLayout;
11785 delete mInsetLayout;
11794 mInsetLayout = 0;
11786 mInsetLayout = 0;
11795
11787
11796 QList<QCPAxis*> axesList = axes();
11788 QList<QCPAxis*> axesList = axes();
11797 for (int i=0; i<axesList.size(); ++i)
11789 for (int i=0; i<axesList.size(); ++i)
11798 removeAxis(axesList.at(i));
11790 removeAxis(axesList.at(i));
11799 }
11791 }
11800
11792
11801 /*!
11793 /*!
@@ -11805,7 +11797,7 QCPAxisRect::~QCPAxisRect()
11805 */
11797 */
11806 int QCPAxisRect::axisCount(QCPAxis::AxisType type) const
11798 int QCPAxisRect::axisCount(QCPAxis::AxisType type) const
11807 {
11799 {
11808 return mAxes.value(type).size();
11800 return mAxes.value(type).size();
11809 }
11801 }
11810
11802
11811 /*!
11803 /*!
@@ -11815,14 +11807,14 int QCPAxisRect::axisCount(QCPAxis::Axis
11815 */
11807 */
11816 QCPAxis *QCPAxisRect::axis(QCPAxis::AxisType type, int index) const
11808 QCPAxis *QCPAxisRect::axis(QCPAxis::AxisType type, int index) const
11817 {
11809 {
11818 QList<QCPAxis*> ax(mAxes.value(type));
11810 QList<QCPAxis*> ax(mAxes.value(type));
11819 if (index >= 0 && index < ax.size())
11811 if (index >= 0 && index < ax.size())
11820 {
11812 {
11821 return ax.at(index);
11813 return ax.at(index);
11822 } else
11814 } else
11823 {
11815 {
11824 qDebug() << Q_FUNC_INFO << "Axis index out of bounds:" << index;
11816 qDebug() << Q_FUNC_INFO << "Axis index out of bounds:" << index;
11825 return 0;
11817 return 0;
11826 }
11818 }
11827 }
11819 }
11828
11820
@@ -11836,16 +11828,16 QCPAxis *QCPAxisRect::axis(QCPAxis::Axis
11836 */
11828 */
11837 QList<QCPAxis*> QCPAxisRect::axes(QCPAxis::AxisTypes types) const
11829 QList<QCPAxis*> QCPAxisRect::axes(QCPAxis::AxisTypes types) const
11838 {
11830 {
11839 QList<QCPAxis*> result;
11831 QList<QCPAxis*> result;
11840 if (types.testFlag(QCPAxis::atLeft))
11832 if (types.testFlag(QCPAxis::atLeft))
11841 result << mAxes.value(QCPAxis::atLeft);
11833 result << mAxes.value(QCPAxis::atLeft);
11842 if (types.testFlag(QCPAxis::atRight))
11834 if (types.testFlag(QCPAxis::atRight))
11843 result << mAxes.value(QCPAxis::atRight);
11835 result << mAxes.value(QCPAxis::atRight);
11844 if (types.testFlag(QCPAxis::atTop))
11836 if (types.testFlag(QCPAxis::atTop))
11845 result << mAxes.value(QCPAxis::atTop);
11837 result << mAxes.value(QCPAxis::atTop);
11846 if (types.testFlag(QCPAxis::atBottom))
11838 if (types.testFlag(QCPAxis::atBottom))
11847 result << mAxes.value(QCPAxis::atBottom);
11839 result << mAxes.value(QCPAxis::atBottom);
11848 return result;
11840 return result;
11849 }
11841 }
11850
11842
11851 /*! \overload
11843 /*! \overload
@@ -11854,14 +11846,14 QList<QCPAxis*> QCPAxisRect::axes(QCPAxi
11854 */
11846 */
11855 QList<QCPAxis*> QCPAxisRect::axes() const
11847 QList<QCPAxis*> QCPAxisRect::axes() const
11856 {
11848 {
11857 QList<QCPAxis*> result;
11849 QList<QCPAxis*> result;
11858 QHashIterator<QCPAxis::AxisType, QList<QCPAxis*> > it(mAxes);
11850 QHashIterator<QCPAxis::AxisType, QList<QCPAxis*> > it(mAxes);
11859 while (it.hasNext())
11851 while (it.hasNext())
11860 {
11852 {
11861 it.next();
11853 it.next();
11862 result << it.value();
11854 result << it.value();
11863 }
11855 }
11864 return result;
11856 return result;
11865 }
11857 }
11866
11858
11867 /*!
11859 /*!
@@ -11885,36 +11877,36 QList<QCPAxis*> QCPAxisRect::axes() cons
11885 */
11877 */
11886 QCPAxis *QCPAxisRect::addAxis(QCPAxis::AxisType type, QCPAxis *axis)
11878 QCPAxis *QCPAxisRect::addAxis(QCPAxis::AxisType type, QCPAxis *axis)
11887 {
11879 {
11888 QCPAxis *newAxis = axis;
11880 QCPAxis *newAxis = axis;
11889 if (!newAxis)
11881 if (!newAxis)
11890 {
11882 {
11891 newAxis = new QCPAxis(this, type);
11883 newAxis = new QCPAxis(this, type);
11892 } else // user provided existing axis instance, do some sanity checks
11884 } else // user provided existing axis instance, do some sanity checks
11893 {
11885 {
11894 if (newAxis->axisType() != type)
11886 if (newAxis->axisType() != type)
11895 {
11887 {
11896 qDebug() << Q_FUNC_INFO << "passed axis has different axis type than specified in type parameter";
11888 qDebug() << Q_FUNC_INFO << "passed axis has different axis type than specified in type parameter";
11897 return 0;
11889 return 0;
11898 }
11890 }
11899 if (newAxis->axisRect() != this)
11891 if (newAxis->axisRect() != this)
11900 {
11892 {
11901 qDebug() << Q_FUNC_INFO << "passed axis doesn't have this axis rect as parent axis rect";
11893 qDebug() << Q_FUNC_INFO << "passed axis doesn't have this axis rect as parent axis rect";
11902 return 0;
11894 return 0;
11903 }
11895 }
11904 if (axes().contains(newAxis))
11896 if (axes().contains(newAxis))
11905 {
11897 {
11906 qDebug() << Q_FUNC_INFO << "passed axis is already owned by this axis rect";
11898 qDebug() << Q_FUNC_INFO << "passed axis is already owned by this axis rect";
11907 return 0;
11899 return 0;
11908 }
11900 }
11909 }
11901 }
11910 if (mAxes[type].size() > 0) // multiple axes on one side, add half-bar axis ending to additional axes with offset
11902 if (mAxes[type].size() > 0) // multiple axes on one side, add half-bar axis ending to additional axes with offset
11911 {
11903 {
11912 bool invert = (type == QCPAxis::atRight) || (type == QCPAxis::atBottom);
11904 bool invert = (type == QCPAxis::atRight) || (type == QCPAxis::atBottom);
11913 newAxis->setLowerEnding(QCPLineEnding(QCPLineEnding::esHalfBar, 6, 10, !invert));
11905 newAxis->setLowerEnding(QCPLineEnding(QCPLineEnding::esHalfBar, 6, 10, !invert));
11914 newAxis->setUpperEnding(QCPLineEnding(QCPLineEnding::esHalfBar, 6, 10, invert));
11906 newAxis->setUpperEnding(QCPLineEnding(QCPLineEnding::esHalfBar, 6, 10, invert));
11915 }
11907 }
11916 mAxes[type].append(newAxis);
11908 mAxes[type].append(newAxis);
11917 return newAxis;
11909 return newAxis;
11918 }
11910 }
11919
11911
11920 /*!
11912 /*!
@@ -11927,16 +11919,16 QCPAxis *QCPAxisRect::addAxis(QCPAxis::A
11927 */
11919 */
11928 QList<QCPAxis*> QCPAxisRect::addAxes(QCPAxis::AxisTypes types)
11920 QList<QCPAxis*> QCPAxisRect::addAxes(QCPAxis::AxisTypes types)
11929 {
11921 {
11930 QList<QCPAxis*> result;
11922 QList<QCPAxis*> result;
11931 if (types.testFlag(QCPAxis::atLeft))
11923 if (types.testFlag(QCPAxis::atLeft))
11932 result << addAxis(QCPAxis::atLeft);
11924 result << addAxis(QCPAxis::atLeft);
11933 if (types.testFlag(QCPAxis::atRight))
11925 if (types.testFlag(QCPAxis::atRight))
11934 result << addAxis(QCPAxis::atRight);
11926 result << addAxis(QCPAxis::atRight);
11935 if (types.testFlag(QCPAxis::atTop))
11927 if (types.testFlag(QCPAxis::atTop))
11936 result << addAxis(QCPAxis::atTop);
11928 result << addAxis(QCPAxis::atTop);
11937 if (types.testFlag(QCPAxis::atBottom))
11929 if (types.testFlag(QCPAxis::atBottom))
11938 result << addAxis(QCPAxis::atBottom);
11930 result << addAxis(QCPAxis::atBottom);
11939 return result;
11931 return result;
11940 }
11932 }
11941
11933
11942 /*!
11934 /*!
@@ -11948,22 +11940,22 QList<QCPAxis*> QCPAxisRect::addAxes(QCP
11948 */
11940 */
11949 bool QCPAxisRect::removeAxis(QCPAxis *axis)
11941 bool QCPAxisRect::removeAxis(QCPAxis *axis)
11950 {
11942 {
11951 // don't access axis->axisType() to provide safety when axis is an invalid pointer, rather go through all axis containers:
11943 // don't access axis->axisType() to provide safety when axis is an invalid pointer, rather go through all axis containers:
11952 QHashIterator<QCPAxis::AxisType, QList<QCPAxis*> > it(mAxes);
11944 QHashIterator<QCPAxis::AxisType, QList<QCPAxis*> > it(mAxes);
11953 while (it.hasNext())
11945 while (it.hasNext())
11954 {
11946 {
11955 it.next();
11947 it.next();
11956 if (it.value().contains(axis))
11948 if (it.value().contains(axis))
11957 {
11949 {
11958 mAxes[it.key()].removeOne(axis);
11950 mAxes[it.key()].removeOne(axis);
11959 if (qobject_cast<QCustomPlot*>(parentPlot())) // make sure this isn't called from QObject dtor when QCustomPlot is already destructed (happens when the axis rect is not in any layout and thus QObject-child of QCustomPlot)
11951 if (qobject_cast<QCustomPlot*>(parentPlot())) // make sure this isn't called from QObject dtor when QCustomPlot is already destructed (happens when the axis rect is not in any layout and thus QObject-child of QCustomPlot)
11960 parentPlot()->axisRemoved(axis);
11952 parentPlot()->axisRemoved(axis);
11961 delete axis;
11953 delete axis;
11962 return true;
11954 return true;
11963 }
11955 }
11964 }
11956 }
11965 qDebug() << Q_FUNC_INFO << "Axis isn't in axis rect:" << reinterpret_cast<quintptr>(axis);
11957 qDebug() << Q_FUNC_INFO << "Axis isn't in axis rect:" << reinterpret_cast<quintptr>(axis);
11966 return false;
11958 return false;
11967 }
11959 }
11968
11960
11969 /*!
11961 /*!
@@ -11994,70 +11986,70 bool QCPAxisRect::removeAxis(QCPAxis *ax
11994 */
11986 */
11995 void QCPAxisRect::setupFullAxesBox(bool connectRanges)
11987 void QCPAxisRect::setupFullAxesBox(bool connectRanges)
11996 {
11988 {
11997 QCPAxis *xAxis, *yAxis, *xAxis2, *yAxis2;
11989 QCPAxis *xAxis, *yAxis, *xAxis2, *yAxis2;
11998 if (axisCount(QCPAxis::atBottom) == 0)
11990 if (axisCount(QCPAxis::atBottom) == 0)
11999 xAxis = addAxis(QCPAxis::atBottom);
11991 xAxis = addAxis(QCPAxis::atBottom);
12000 else
11992 else
12001 xAxis = axis(QCPAxis::atBottom);
11993 xAxis = axis(QCPAxis::atBottom);
12002
11994
12003 if (axisCount(QCPAxis::atLeft) == 0)
11995 if (axisCount(QCPAxis::atLeft) == 0)
12004 yAxis = addAxis(QCPAxis::atLeft);
11996 yAxis = addAxis(QCPAxis::atLeft);
12005 else
11997 else
12006 yAxis = axis(QCPAxis::atLeft);
11998 yAxis = axis(QCPAxis::atLeft);
12007
11999
12008 if (axisCount(QCPAxis::atTop) == 0)
12000 if (axisCount(QCPAxis::atTop) == 0)
12009 xAxis2 = addAxis(QCPAxis::atTop);
12001 xAxis2 = addAxis(QCPAxis::atTop);
12010 else
12002 else
12011 xAxis2 = axis(QCPAxis::atTop);
12003 xAxis2 = axis(QCPAxis::atTop);
12012
12004
12013 if (axisCount(QCPAxis::atRight) == 0)
12005 if (axisCount(QCPAxis::atRight) == 0)
12014 yAxis2 = addAxis(QCPAxis::atRight);
12006 yAxis2 = addAxis(QCPAxis::atRight);
12015 else
12007 else
12016 yAxis2 = axis(QCPAxis::atRight);
12008 yAxis2 = axis(QCPAxis::atRight);
12017
12009
12018 xAxis->setVisible(true);
12010 xAxis->setVisible(true);
12019 yAxis->setVisible(true);
12011 yAxis->setVisible(true);
12020 xAxis2->setVisible(true);
12012 xAxis2->setVisible(true);
12021 yAxis2->setVisible(true);
12013 yAxis2->setVisible(true);
12022 xAxis2->setTickLabels(false);
12014 xAxis2->setTickLabels(false);
12023 yAxis2->setTickLabels(false);
12015 yAxis2->setTickLabels(false);
12024
12016
12025 xAxis2->setRange(xAxis->range());
12017 xAxis2->setRange(xAxis->range());
12026 xAxis2->setRangeReversed(xAxis->rangeReversed());
12018 xAxis2->setRangeReversed(xAxis->rangeReversed());
12027 xAxis2->setScaleType(xAxis->scaleType());
12019 xAxis2->setScaleType(xAxis->scaleType());
12028 xAxis2->setScaleLogBase(xAxis->scaleLogBase());
12020 xAxis2->setScaleLogBase(xAxis->scaleLogBase());
12029 xAxis2->setTicks(xAxis->ticks());
12021 xAxis2->setTicks(xAxis->ticks());
12030 xAxis2->setAutoTickCount(xAxis->autoTickCount());
12022 xAxis2->setAutoTickCount(xAxis->autoTickCount());
12031 xAxis2->setSubTickCount(xAxis->subTickCount());
12023 xAxis2->setSubTickCount(xAxis->subTickCount());
12032 xAxis2->setAutoSubTicks(xAxis->autoSubTicks());
12024 xAxis2->setAutoSubTicks(xAxis->autoSubTicks());
12033 xAxis2->setTickStep(xAxis->tickStep());
12025 xAxis2->setTickStep(xAxis->tickStep());
12034 xAxis2->setAutoTickStep(xAxis->autoTickStep());
12026 xAxis2->setAutoTickStep(xAxis->autoTickStep());
12035 xAxis2->setNumberFormat(xAxis->numberFormat());
12027 xAxis2->setNumberFormat(xAxis->numberFormat());
12036 xAxis2->setNumberPrecision(xAxis->numberPrecision());
12028 xAxis2->setNumberPrecision(xAxis->numberPrecision());
12037 xAxis2->setTickLabelType(xAxis->tickLabelType());
12029 xAxis2->setTickLabelType(xAxis->tickLabelType());
12038 xAxis2->setDateTimeFormat(xAxis->dateTimeFormat());
12030 xAxis2->setDateTimeFormat(xAxis->dateTimeFormat());
12039 xAxis2->setDateTimeSpec(xAxis->dateTimeSpec());
12031 xAxis2->setDateTimeSpec(xAxis->dateTimeSpec());
12040
12032
12041 yAxis2->setRange(yAxis->range());
12033 yAxis2->setRange(yAxis->range());
12042 yAxis2->setRangeReversed(yAxis->rangeReversed());
12034 yAxis2->setRangeReversed(yAxis->rangeReversed());
12043 yAxis2->setScaleType(yAxis->scaleType());
12035 yAxis2->setScaleType(yAxis->scaleType());
12044 yAxis2->setScaleLogBase(yAxis->scaleLogBase());
12036 yAxis2->setScaleLogBase(yAxis->scaleLogBase());
12045 yAxis2->setTicks(yAxis->ticks());
12037 yAxis2->setTicks(yAxis->ticks());
12046 yAxis2->setAutoTickCount(yAxis->autoTickCount());
12038 yAxis2->setAutoTickCount(yAxis->autoTickCount());
12047 yAxis2->setSubTickCount(yAxis->subTickCount());
12039 yAxis2->setSubTickCount(yAxis->subTickCount());
12048 yAxis2->setAutoSubTicks(yAxis->autoSubTicks());
12040 yAxis2->setAutoSubTicks(yAxis->autoSubTicks());
12049 yAxis2->setTickStep(yAxis->tickStep());
12041 yAxis2->setTickStep(yAxis->tickStep());
12050 yAxis2->setAutoTickStep(yAxis->autoTickStep());
12042 yAxis2->setAutoTickStep(yAxis->autoTickStep());
12051 yAxis2->setNumberFormat(yAxis->numberFormat());
12043 yAxis2->setNumberFormat(yAxis->numberFormat());
12052 yAxis2->setNumberPrecision(yAxis->numberPrecision());
12044 yAxis2->setNumberPrecision(yAxis->numberPrecision());
12053 yAxis2->setTickLabelType(yAxis->tickLabelType());
12045 yAxis2->setTickLabelType(yAxis->tickLabelType());
12054 yAxis2->setDateTimeFormat(yAxis->dateTimeFormat());
12046 yAxis2->setDateTimeFormat(yAxis->dateTimeFormat());
12055 yAxis2->setDateTimeSpec(yAxis->dateTimeSpec());
12047 yAxis2->setDateTimeSpec(yAxis->dateTimeSpec());
12056
12048
12057 if (connectRanges)
12049 if (connectRanges)
12058 {
12050 {
12059 connect(xAxis, SIGNAL(rangeChanged(QCPRange)), xAxis2, SLOT(setRange(QCPRange)));
12051 connect(xAxis, SIGNAL(rangeChanged(QCPRange)), xAxis2, SLOT(setRange(QCPRange)));
12060 connect(yAxis, SIGNAL(rangeChanged(QCPRange)), yAxis2, SLOT(setRange(QCPRange)));
12052 connect(yAxis, SIGNAL(rangeChanged(QCPRange)), yAxis2, SLOT(setRange(QCPRange)));
12061 }
12053 }
12062 }
12054 }
12063
12055
@@ -12071,14 +12063,14 void QCPAxisRect::setupFullAxesBox(bool
12071 */
12063 */
12072 QList<QCPAbstractPlottable*> QCPAxisRect::plottables() const
12064 QList<QCPAbstractPlottable*> QCPAxisRect::plottables() const
12073 {
12065 {
12074 // Note: don't append all QCPAxis::plottables() into a list, because we might get duplicate entries
12066 // Note: don't append all QCPAxis::plottables() into a list, because we might get duplicate entries
12075 QList<QCPAbstractPlottable*> result;
12067 QList<QCPAbstractPlottable*> result;
12076 for (int i=0; i<mParentPlot->mPlottables.size(); ++i)
12068 for (int i=0; i<mParentPlot->mPlottables.size(); ++i)
12077 {
12069 {
12078 if (mParentPlot->mPlottables.at(i)->keyAxis()->axisRect() == this ||mParentPlot->mPlottables.at(i)->valueAxis()->axisRect() == this)
12070 if (mParentPlot->mPlottables.at(i)->keyAxis()->axisRect() == this ||mParentPlot->mPlottables.at(i)->valueAxis()->axisRect() == this)
12079 result.append(mParentPlot->mPlottables.at(i));
12071 result.append(mParentPlot->mPlottables.at(i));
12080 }
12072 }
12081 return result;
12073 return result;
12082 }
12074 }
12083
12075
12084 /*!
12076 /*!
@@ -12091,14 +12083,14 QList<QCPAbstractPlottable*> QCPAxisRect
12091 */
12083 */
12092 QList<QCPGraph*> QCPAxisRect::graphs() const
12084 QList<QCPGraph*> QCPAxisRect::graphs() const
12093 {
12085 {
12094 // Note: don't append all QCPAxis::graphs() into a list, because we might get duplicate entries
12086 // Note: don't append all QCPAxis::graphs() into a list, because we might get duplicate entries
12095 QList<QCPGraph*> result;
12087 QList<QCPGraph*> result;
12096 for (int i=0; i<mParentPlot->mGraphs.size(); ++i)
12088 for (int i=0; i<mParentPlot->mGraphs.size(); ++i)
12097 {
12089 {
12098 if (mParentPlot->mGraphs.at(i)->keyAxis()->axisRect() == this || mParentPlot->mGraphs.at(i)->valueAxis()->axisRect() == this)
12090 if (mParentPlot->mGraphs.at(i)->keyAxis()->axisRect() == this || mParentPlot->mGraphs.at(i)->valueAxis()->axisRect() == this)
12099 result.append(mParentPlot->mGraphs.at(i));
12091 result.append(mParentPlot->mGraphs.at(i));
12100 }
12092 }
12101 return result;
12093 return result;
12102 }
12094 }
12103
12095
12104 /*!
12096 /*!
@@ -12113,29 +12105,29 QList<QCPGraph*> QCPAxisRect::graphs() c
12113 */
12105 */
12114 QList<QCPAbstractItem *> QCPAxisRect::items() const
12106 QList<QCPAbstractItem *> QCPAxisRect::items() const
12115 {
12107 {
12116 // Note: don't just append all QCPAxis::items() into a list, because we might get duplicate entries
12108 // Note: don't just append all QCPAxis::items() into a list, because we might get duplicate entries
12117 // and miss those items that have this axis rect as clipAxisRect.
12109 // and miss those items that have this axis rect as clipAxisRect.
12118 QList<QCPAbstractItem*> result;
12110 QList<QCPAbstractItem*> result;
12119 for (int itemId=0; itemId<mParentPlot->mItems.size(); ++itemId)
12111 for (int itemId=0; itemId<mParentPlot->mItems.size(); ++itemId)
12120 {
12112 {
12121 if (mParentPlot->mItems.at(itemId)->clipAxisRect() == this)
12113 if (mParentPlot->mItems.at(itemId)->clipAxisRect() == this)
12122 {
12114 {
12123 result.append(mParentPlot->mItems.at(itemId));
12115 result.append(mParentPlot->mItems.at(itemId));
12124 continue;
12116 continue;
12125 }
12117 }
12126 QList<QCPItemPosition*> positions = mParentPlot->mItems.at(itemId)->positions();
12118 QList<QCPItemPosition*> positions = mParentPlot->mItems.at(itemId)->positions();
12127 for (int posId=0; posId<positions.size(); ++posId)
12119 for (int posId=0; posId<positions.size(); ++posId)
12128 {
12120 {
12129 if (positions.at(posId)->axisRect() == this ||
12121 if (positions.at(posId)->axisRect() == this ||
12130 positions.at(posId)->keyAxis()->axisRect() == this ||
12122 positions.at(posId)->keyAxis()->axisRect() == this ||
12131 positions.at(posId)->valueAxis()->axisRect() == this)
12123 positions.at(posId)->valueAxis()->axisRect() == this)
12132 {
12124 {
12133 result.append(mParentPlot->mItems.at(itemId));
12125 result.append(mParentPlot->mItems.at(itemId));
12134 break;
12126 break;
12135 }
12127 }
12136 }
12128 }
12137 }
12129 }
12138 return result;
12130 return result;
12139 }
12131 }
12140
12132
12141 /*!
12133 /*!
@@ -12148,52 +12140,52 QList<QCPAbstractItem *> QCPAxisRect::it
12148 */
12140 */
12149 void QCPAxisRect::update(UpdatePhase phase)
12141 void QCPAxisRect::update(UpdatePhase phase)
12150 {
12142 {
12151 QCPLayoutElement::update(phase);
12143 QCPLayoutElement::update(phase);
12152
12144
12153 switch (phase)
12145 switch (phase)
12154 {
12146 {
12155 case upPreparation:
12147 case upPreparation:
12156 {
12148 {
12157 QList<QCPAxis*> allAxes = axes();
12149 QList<QCPAxis*> allAxes = axes();
12158 for (int i=0; i<allAxes.size(); ++i)
12150 for (int i=0; i<allAxes.size(); ++i)
12159 allAxes.at(i)->setupTickVectors();
12151 allAxes.at(i)->setupTickVectors();
12160 break;
12152 break;
12161 }
12153 }
12162 case upLayout:
12154 case upLayout:
12163 {
12155 {
12164 mInsetLayout->setOuterRect(rect());
12156 mInsetLayout->setOuterRect(rect());
12165 break;
12157 break;
12166 }
12158 }
12167 default: break;
12159 default: break;
12168 }
12160 }
12169
12161
12170 // pass update call on to inset layout (doesn't happen automatically, because QCPAxisRect doesn't derive from QCPLayout):
12162 // pass update call on to inset layout (doesn't happen automatically, because QCPAxisRect doesn't derive from QCPLayout):
12171 mInsetLayout->update(phase);
12163 mInsetLayout->update(phase);
12172 }
12164 }
12173
12165
12174 /* inherits documentation from base class */
12166 /* inherits documentation from base class */
12175 QList<QCPLayoutElement*> QCPAxisRect::elements(bool recursive) const
12167 QList<QCPLayoutElement*> QCPAxisRect::elements(bool recursive) const
12176 {
12168 {
12177 QList<QCPLayoutElement*> result;
12169 QList<QCPLayoutElement*> result;
12178 if (mInsetLayout)
12170 if (mInsetLayout)
12179 {
12171 {
12180 result << mInsetLayout;
12172 result << mInsetLayout;
12181 if (recursive)
12173 if (recursive)
12182 result << mInsetLayout->elements(recursive);
12174 result << mInsetLayout->elements(recursive);
12183 }
12175 }
12184 return result;
12176 return result;
12185 }
12177 }
12186
12178
12187 /* inherits documentation from base class */
12179 /* inherits documentation from base class */
12188 void QCPAxisRect::applyDefaultAntialiasingHint(QCPPainter *painter) const
12180 void QCPAxisRect::applyDefaultAntialiasingHint(QCPPainter *painter) const
12189 {
12181 {
12190 painter->setAntialiasing(false);
12182 painter->setAntialiasing(false);
12191 }
12183 }
12192
12184
12193 /* inherits documentation from base class */
12185 /* inherits documentation from base class */
12194 void QCPAxisRect::draw(QCPPainter *painter)
12186 void QCPAxisRect::draw(QCPPainter *painter)
12195 {
12187 {
12196 drawBackground(painter);
12188 drawBackground(painter);
12197 }
12189 }
12198
12190
12199 /*!
12191 /*!
@@ -12213,8 +12205,8 void QCPAxisRect::draw(QCPPainter *paint
12213 */
12205 */
12214 void QCPAxisRect::setBackground(const QPixmap &pm)
12206 void QCPAxisRect::setBackground(const QPixmap &pm)
12215 {
12207 {
12216 mBackgroundPixmap = pm;
12208 mBackgroundPixmap = pm;
12217 mScaledBackgroundPixmap = QPixmap();
12209 mScaledBackgroundPixmap = QPixmap();
12218 }
12210 }
12219
12211
12220 /*! \overload
12212 /*! \overload
@@ -12232,7 +12224,7 void QCPAxisRect::setBackground(const QP
12232 */
12224 */
12233 void QCPAxisRect::setBackground(const QBrush &brush)
12225 void QCPAxisRect::setBackground(const QBrush &brush)
12234 {
12226 {
12235 mBackgroundBrush = brush;
12227 mBackgroundBrush = brush;
12236 }
12228 }
12237
12229
12238 /*! \overload
12230 /*! \overload
@@ -12244,10 +12236,10 void QCPAxisRect::setBackground(const QB
12244 */
12236 */
12245 void QCPAxisRect::setBackground(const QPixmap &pm, bool scaled, Qt::AspectRatioMode mode)
12237 void QCPAxisRect::setBackground(const QPixmap &pm, bool scaled, Qt::AspectRatioMode mode)
12246 {
12238 {
12247 mBackgroundPixmap = pm;
12239 mBackgroundPixmap = pm;
12248 mScaledBackgroundPixmap = QPixmap();
12240 mScaledBackgroundPixmap = QPixmap();
12249 mBackgroundScaled = scaled;
12241 mBackgroundScaled = scaled;
12250 mBackgroundScaledMode = mode;
12242 mBackgroundScaledMode = mode;
12251 }
12243 }
12252
12244
12253 /*!
12245 /*!
@@ -12262,7 +12254,7 void QCPAxisRect::setBackground(const QP
12262 */
12254 */
12263 void QCPAxisRect::setBackgroundScaled(bool scaled)
12255 void QCPAxisRect::setBackgroundScaled(bool scaled)
12264 {
12256 {
12265 mBackgroundScaled = scaled;
12257 mBackgroundScaled = scaled;
12266 }
12258 }
12267
12259
12268 /*!
12260 /*!
@@ -12272,7 +12264,7 void QCPAxisRect::setBackgroundScaled(bo
12272 */
12264 */
12273 void QCPAxisRect::setBackgroundScaledMode(Qt::AspectRatioMode mode)
12265 void QCPAxisRect::setBackgroundScaledMode(Qt::AspectRatioMode mode)
12274 {
12266 {
12275 mBackgroundScaledMode = mode;
12267 mBackgroundScaledMode = mode;
12276 }
12268 }
12277
12269
12278 /*!
12270 /*!
@@ -12282,7 +12274,7 void QCPAxisRect::setBackgroundScaledMod
12282 */
12274 */
12283 QCPAxis *QCPAxisRect::rangeDragAxis(Qt::Orientation orientation)
12275 QCPAxis *QCPAxisRect::rangeDragAxis(Qt::Orientation orientation)
12284 {
12276 {
12285 return (orientation == Qt::Horizontal ? mRangeDragHorzAxis.data() : mRangeDragVertAxis.data());
12277 return (orientation == Qt::Horizontal ? mRangeDragHorzAxis.data() : mRangeDragVertAxis.data());
12286 }
12278 }
12287
12279
12288 /*!
12280 /*!
@@ -12292,7 +12284,7 QCPAxis *QCPAxisRect::rangeDragAxis(Qt::
12292 */
12284 */
12293 QCPAxis *QCPAxisRect::rangeZoomAxis(Qt::Orientation orientation)
12285 QCPAxis *QCPAxisRect::rangeZoomAxis(Qt::Orientation orientation)
12294 {
12286 {
12295 return (orientation == Qt::Horizontal ? mRangeZoomHorzAxis.data() : mRangeZoomVertAxis.data());
12287 return (orientation == Qt::Horizontal ? mRangeZoomHorzAxis.data() : mRangeZoomVertAxis.data());
12296 }
12288 }
12297
12289
12298 /*!
12290 /*!
@@ -12302,7 +12294,7 QCPAxis *QCPAxisRect::rangeZoomAxis(Qt::
12302 */
12294 */
12303 double QCPAxisRect::rangeZoomFactor(Qt::Orientation orientation)
12295 double QCPAxisRect::rangeZoomFactor(Qt::Orientation orientation)
12304 {
12296 {
12305 return (orientation == Qt::Horizontal ? mRangeZoomFactorHorz : mRangeZoomFactorVert);
12297 return (orientation == Qt::Horizontal ? mRangeZoomFactorHorz : mRangeZoomFactorVert);
12306 }
12298 }
12307
12299
12308 /*!
12300 /*!
@@ -12323,7 +12315,7 double QCPAxisRect::rangeZoomFactor(Qt::
12323 */
12315 */
12324 void QCPAxisRect::setRangeDrag(Qt::Orientations orientations)
12316 void QCPAxisRect::setRangeDrag(Qt::Orientations orientations)
12325 {
12317 {
12326 mRangeDrag = orientations;
12318 mRangeDrag = orientations;
12327 }
12319 }
12328
12320
12329 /*!
12321 /*!
@@ -12343,7 +12335,7 void QCPAxisRect::setRangeDrag(Qt::Orien
12343 */
12335 */
12344 void QCPAxisRect::setRangeZoom(Qt::Orientations orientations)
12336 void QCPAxisRect::setRangeZoom(Qt::Orientations orientations)
12345 {
12337 {
12346 mRangeZoom = orientations;
12338 mRangeZoom = orientations;
12347 }
12339 }
12348
12340
12349 /*!
12341 /*!
@@ -12354,8 +12346,8 void QCPAxisRect::setRangeZoom(Qt::Orien
12354 */
12346 */
12355 void QCPAxisRect::setRangeDragAxes(QCPAxis *horizontal, QCPAxis *vertical)
12347 void QCPAxisRect::setRangeDragAxes(QCPAxis *horizontal, QCPAxis *vertical)
12356 {
12348 {
12357 mRangeDragHorzAxis = horizontal;
12349 mRangeDragHorzAxis = horizontal;
12358 mRangeDragVertAxis = vertical;
12350 mRangeDragVertAxis = vertical;
12359 }
12351 }
12360
12352
12361 /*!
12353 /*!
@@ -12367,8 +12359,8 void QCPAxisRect::setRangeDragAxes(QCPAx
12367 */
12359 */
12368 void QCPAxisRect::setRangeZoomAxes(QCPAxis *horizontal, QCPAxis *vertical)
12360 void QCPAxisRect::setRangeZoomAxes(QCPAxis *horizontal, QCPAxis *vertical)
12369 {
12361 {
12370 mRangeZoomHorzAxis = horizontal;
12362 mRangeZoomHorzAxis = horizontal;
12371 mRangeZoomVertAxis = vertical;
12363 mRangeZoomVertAxis = vertical;
12372 }
12364 }
12373
12365
12374 /*!
12366 /*!
@@ -12383,8 +12375,8 void QCPAxisRect::setRangeZoomAxes(QCPAx
12383 */
12375 */
12384 void QCPAxisRect::setRangeZoomFactor(double horizontalFactor, double verticalFactor)
12376 void QCPAxisRect::setRangeZoomFactor(double horizontalFactor, double verticalFactor)
12385 {
12377 {
12386 mRangeZoomFactorHorz = horizontalFactor;
12378 mRangeZoomFactorHorz = horizontalFactor;
12387 mRangeZoomFactorVert = verticalFactor;
12379 mRangeZoomFactorVert = verticalFactor;
12388 }
12380 }
12389
12381
12390 /*! \overload
12382 /*! \overload
@@ -12393,8 +12385,8 void QCPAxisRect::setRangeZoomFactor(dou
12393 */
12385 */
12394 void QCPAxisRect::setRangeZoomFactor(double factor)
12386 void QCPAxisRect::setRangeZoomFactor(double factor)
12395 {
12387 {
12396 mRangeZoomFactorHorz = factor;
12388 mRangeZoomFactorHorz = factor;
12397 mRangeZoomFactorVert = factor;
12389 mRangeZoomFactorVert = factor;
12398 }
12390 }
12399
12391
12400 /*! \internal
12392 /*! \internal
@@ -12417,24 +12409,24 void QCPAxisRect::setRangeZoomFactor(dou
12417 */
12409 */
12418 void QCPAxisRect::drawBackground(QCPPainter *painter)
12410 void QCPAxisRect::drawBackground(QCPPainter *painter)
12419 {
12411 {
12420 // draw background fill:
12412 // draw background fill:
12421 if (mBackgroundBrush != Qt::NoBrush)
12413 if (mBackgroundBrush != Qt::NoBrush)
12422 painter->fillRect(mRect, mBackgroundBrush);
12414 painter->fillRect(mRect, mBackgroundBrush);
12423
12415
12424 // draw background pixmap (on top of fill, if brush specified):
12416 // draw background pixmap (on top of fill, if brush specified):
12425 if (!mBackgroundPixmap.isNull())
12417 if (!mBackgroundPixmap.isNull())
12426 {
12418 {
12427 if (mBackgroundScaled)
12419 if (mBackgroundScaled)
12428 {
12420 {
12429 // check whether mScaledBackground needs to be updated:
12421 // check whether mScaledBackground needs to be updated:
12430 QSize scaledSize(mBackgroundPixmap.size());
12422 QSize scaledSize(mBackgroundPixmap.size());
12431 scaledSize.scale(mRect.size(), mBackgroundScaledMode);
12423 scaledSize.scale(mRect.size(), mBackgroundScaledMode);
12432 if (mScaledBackgroundPixmap.size() != scaledSize)
12424 if (mScaledBackgroundPixmap.size() != scaledSize)
12433 mScaledBackgroundPixmap = mBackgroundPixmap.scaled(mRect.size(), mBackgroundScaledMode, Qt::SmoothTransformation);
12425 mScaledBackgroundPixmap = mBackgroundPixmap.scaled(mRect.size(), mBackgroundScaledMode, Qt::SmoothTransformation);
12434 painter->drawPixmap(mRect.topLeft(), mScaledBackgroundPixmap, QRect(0, 0, mRect.width(), mRect.height()) & mScaledBackgroundPixmap.rect());
12426 painter->drawPixmap(mRect.topLeft(), mScaledBackgroundPixmap, QRect(0, 0, mRect.width(), mRect.height()) & mScaledBackgroundPixmap.rect());
12435 } else
12427 } else
12436 {
12428 {
12437 painter->drawPixmap(mRect.topLeft(), mBackgroundPixmap, QRect(0, 0, mRect.width(), mRect.height()));
12429 painter->drawPixmap(mRect.topLeft(), mBackgroundPixmap, QRect(0, 0, mRect.width(), mRect.height()));
12438 }
12430 }
12439 }
12431 }
12440 }
12432 }
@@ -12451,38 +12443,38 void QCPAxisRect::drawBackground(QCPPain
12451 */
12443 */
12452 void QCPAxisRect::updateAxesOffset(QCPAxis::AxisType type)
12444 void QCPAxisRect::updateAxesOffset(QCPAxis::AxisType type)
12453 {
12445 {
12454 const QList<QCPAxis*> axesList = mAxes.value(type);
12446 const QList<QCPAxis*> axesList = mAxes.value(type);
12455 if (axesList.isEmpty())
12447 if (axesList.isEmpty())
12456 return;
12448 return;
12457
12449
12458 bool isFirstVisible = !axesList.first()->visible(); // if the first axis is visible, the second axis (which is where the loop starts) isn't the first visible axis, so initialize with false
12450 bool isFirstVisible = !axesList.first()->visible(); // if the first axis is visible, the second axis (which is where the loop starts) isn't the first visible axis, so initialize with false
12459 for (int i=1; i<axesList.size(); ++i)
12451 for (int i=1; i<axesList.size(); ++i)
12460 {
12452 {
12461 int offset = axesList.at(i-1)->offset() + axesList.at(i-1)->calculateMargin();
12453 int offset = axesList.at(i-1)->offset() + axesList.at(i-1)->calculateMargin();
12462 if (axesList.at(i)->visible()) // only add inner tick length to offset if this axis is visible and it's not the first visible one (might happen if true first axis is invisible)
12454 if (axesList.at(i)->visible()) // only add inner tick length to offset if this axis is visible and it's not the first visible one (might happen if true first axis is invisible)
12463 {
12455 {
12464 if (!isFirstVisible)
12456 if (!isFirstVisible)
12465 offset += axesList.at(i)->tickLengthIn();
12457 offset += axesList.at(i)->tickLengthIn();
12466 isFirstVisible = false;
12458 isFirstVisible = false;
12467 }
12459 }
12468 axesList.at(i)->setOffset(offset);
12460 axesList.at(i)->setOffset(offset);
12469 }
12461 }
12470 }
12462 }
12471
12463
12472 /* inherits documentation from base class */
12464 /* inherits documentation from base class */
12473 int QCPAxisRect::calculateAutoMargin(QCP::MarginSide side)
12465 int QCPAxisRect::calculateAutoMargin(QCP::MarginSide side)
12474 {
12466 {
12475 if (!mAutoMargins.testFlag(side))
12467 if (!mAutoMargins.testFlag(side))
12476 qDebug() << Q_FUNC_INFO << "Called with side that isn't specified as auto margin";
12468 qDebug() << Q_FUNC_INFO << "Called with side that isn't specified as auto margin";
12477
12469
12478 updateAxesOffset(QCPAxis::marginSideToAxisType(side));
12470 updateAxesOffset(QCPAxis::marginSideToAxisType(side));
12479
12471
12480 // note: only need to look at the last (outer most) axis to determine the total margin, due to updateAxisOffset call
12472 // note: only need to look at the last (outer most) axis to determine the total margin, due to updateAxisOffset call
12481 const QList<QCPAxis*> axesList = mAxes.value(QCPAxis::marginSideToAxisType(side));
12473 const QList<QCPAxis*> axesList = mAxes.value(QCPAxis::marginSideToAxisType(side));
12482 if (axesList.size() > 0)
12474 if (axesList.size() > 0)
12483 return axesList.last()->offset() + axesList.last()->calculateMargin();
12475 return axesList.last()->offset() + axesList.last()->calculateMargin();
12484 else
12476 else
12485 return 0;
12477 return 0;
12486 }
12478 }
12487
12479
12488 /*! \internal
12480 /*! \internal
@@ -12498,23 +12490,23 int QCPAxisRect::calculateAutoMargin(QCP
12498 */
12490 */
12499 void QCPAxisRect::mousePressEvent(QMouseEvent *event)
12491 void QCPAxisRect::mousePressEvent(QMouseEvent *event)
12500 {
12492 {
12501 mDragStart = event->pos(); // need this even when not LeftButton is pressed, to determine in releaseEvent whether it was a full click (no position change between press and release)
12493 mDragStart = event->pos(); // need this even when not LeftButton is pressed, to determine in releaseEvent whether it was a full click (no position change between press and release)
12502 if (event->buttons() & Qt::LeftButton)
12494 if (event->buttons() & Qt::LeftButton)
12503 {
12495 {
12504 mDragging = true;
12496 mDragging = true;
12505 // initialize antialiasing backup in case we start dragging:
12497 // initialize antialiasing backup in case we start dragging:
12506 if (mParentPlot->noAntialiasingOnDrag())
12498 if (mParentPlot->noAntialiasingOnDrag())
12507 {
12499 {
12508 mAADragBackup = mParentPlot->antialiasedElements();
12500 mAADragBackup = mParentPlot->antialiasedElements();
12509 mNotAADragBackup = mParentPlot->notAntialiasedElements();
12501 mNotAADragBackup = mParentPlot->notAntialiasedElements();
12510 }
12502 }
12511 // Mouse range dragging interaction:
12503 // Mouse range dragging interaction:
12512 if (mParentPlot->interactions().testFlag(QCP::iRangeDrag))
12504 if (mParentPlot->interactions().testFlag(QCP::iRangeDrag))
12513 {
12505 {
12514 if (mRangeDragHorzAxis)
12506 if (mRangeDragHorzAxis)
12515 mDragStartHorzRange = mRangeDragHorzAxis.data()->range();
12507 mDragStartHorzRange = mRangeDragHorzAxis.data()->range();
12516 if (mRangeDragVertAxis)
12508 if (mRangeDragVertAxis)
12517 mDragStartVertRange = mRangeDragVertAxis.data()->range();
12509 mDragStartVertRange = mRangeDragVertAxis.data()->range();
12518 }
12510 }
12519 }
12511 }
12520 }
12512 }
@@ -12528,44 +12520,44 void QCPAxisRect::mousePressEvent(QMouse
12528 */
12520 */
12529 void QCPAxisRect::mouseMoveEvent(QMouseEvent *event)
12521 void QCPAxisRect::mouseMoveEvent(QMouseEvent *event)
12530 {
12522 {
12531 // Mouse range dragging interaction:
12523 // Mouse range dragging interaction:
12532 if (mDragging && mParentPlot->interactions().testFlag(QCP::iRangeDrag))
12524 if (mDragging && mParentPlot->interactions().testFlag(QCP::iRangeDrag))
12533 {
12525 {
12534 if (mRangeDrag.testFlag(Qt::Horizontal))
12526 if (mRangeDrag.testFlag(Qt::Horizontal))
12535 {
12527 {
12536 if (QCPAxis *rangeDragHorzAxis = mRangeDragHorzAxis.data())
12528 if (QCPAxis *rangeDragHorzAxis = mRangeDragHorzAxis.data())
12537 {
12529 {
12538 if (rangeDragHorzAxis->mScaleType == QCPAxis::stLinear)
12530 if (rangeDragHorzAxis->mScaleType == QCPAxis::stLinear)
12539 {
12531 {
12540 double diff = rangeDragHorzAxis->pixelToCoord(mDragStart.x()) - rangeDragHorzAxis->pixelToCoord(event->pos().x());
12532 double diff = rangeDragHorzAxis->pixelToCoord(mDragStart.x()) - rangeDragHorzAxis->pixelToCoord(event->pos().x());
12541 rangeDragHorzAxis->setRange(mDragStartHorzRange.lower+diff, mDragStartHorzRange.upper+diff);
12533 rangeDragHorzAxis->setRange(mDragStartHorzRange.lower+diff, mDragStartHorzRange.upper+diff);
12542 } else if (rangeDragHorzAxis->mScaleType == QCPAxis::stLogarithmic)
12534 } else if (rangeDragHorzAxis->mScaleType == QCPAxis::stLogarithmic)
12543 {
12535 {
12544 double diff = rangeDragHorzAxis->pixelToCoord(mDragStart.x()) / rangeDragHorzAxis->pixelToCoord(event->pos().x());
12536 double diff = rangeDragHorzAxis->pixelToCoord(mDragStart.x()) / rangeDragHorzAxis->pixelToCoord(event->pos().x());
12545 rangeDragHorzAxis->setRange(mDragStartHorzRange.lower*diff, mDragStartHorzRange.upper*diff);
12537 rangeDragHorzAxis->setRange(mDragStartHorzRange.lower*diff, mDragStartHorzRange.upper*diff);
12546 }
12538 }
12547 }
12539 }
12548 }
12540 }
12549 if (mRangeDrag.testFlag(Qt::Vertical))
12541 if (mRangeDrag.testFlag(Qt::Vertical))
12550 {
12542 {
12551 if (QCPAxis *rangeDragVertAxis = mRangeDragVertAxis.data())
12543 if (QCPAxis *rangeDragVertAxis = mRangeDragVertAxis.data())
12552 {
12544 {
12553 if (rangeDragVertAxis->mScaleType == QCPAxis::stLinear)
12545 if (rangeDragVertAxis->mScaleType == QCPAxis::stLinear)
12554 {
12546 {
12555 double diff = rangeDragVertAxis->pixelToCoord(mDragStart.y()) - rangeDragVertAxis->pixelToCoord(event->pos().y());
12547 double diff = rangeDragVertAxis->pixelToCoord(mDragStart.y()) - rangeDragVertAxis->pixelToCoord(event->pos().y());
12556 rangeDragVertAxis->setRange(mDragStartVertRange.lower+diff, mDragStartVertRange.upper+diff);
12548 rangeDragVertAxis->setRange(mDragStartVertRange.lower+diff, mDragStartVertRange.upper+diff);
12557 } else if (rangeDragVertAxis->mScaleType == QCPAxis::stLogarithmic)
12549 } else if (rangeDragVertAxis->mScaleType == QCPAxis::stLogarithmic)
12558 {
12550 {
12559 double diff = rangeDragVertAxis->pixelToCoord(mDragStart.y()) / rangeDragVertAxis->pixelToCoord(event->pos().y());
12551 double diff = rangeDragVertAxis->pixelToCoord(mDragStart.y()) / rangeDragVertAxis->pixelToCoord(event->pos().y());
12560 rangeDragVertAxis->setRange(mDragStartVertRange.lower*diff, mDragStartVertRange.upper*diff);
12552 rangeDragVertAxis->setRange(mDragStartVertRange.lower*diff, mDragStartVertRange.upper*diff);
12561 }
12553 }
12562 }
12554 }
12563 }
12555 }
12564 if (mRangeDrag != 0) // if either vertical or horizontal drag was enabled, do a replot
12556 if (mRangeDrag != 0) // if either vertical or horizontal drag was enabled, do a replot
12565 {
12557 {
12566 if (mParentPlot->noAntialiasingOnDrag())
12558 if (mParentPlot->noAntialiasingOnDrag())
12567 mParentPlot->setNotAntialiasedElements(QCP::aeAll);
12559 mParentPlot->setNotAntialiasedElements(QCP::aeAll);
12568 mParentPlot->replot();
12560 mParentPlot->replot();
12569 }
12561 }
12570 }
12562 }
12571 }
12563 }
@@ -12573,12 +12565,12 void QCPAxisRect::mouseMoveEvent(QMouseE
12573 /* inherits documentation from base class */
12565 /* inherits documentation from base class */
12574 void QCPAxisRect::mouseReleaseEvent(QMouseEvent *event)
12566 void QCPAxisRect::mouseReleaseEvent(QMouseEvent *event)
12575 {
12567 {
12576 Q_UNUSED(event)
12568 Q_UNUSED(event)
12577 mDragging = false;
12569 mDragging = false;
12578 if (mParentPlot->noAntialiasingOnDrag())
12570 if (mParentPlot->noAntialiasingOnDrag())
12579 {
12571 {
12580 mParentPlot->setAntialiasedElements(mAADragBackup);
12572 mParentPlot->setAntialiasedElements(mAADragBackup);
12581 mParentPlot->setNotAntialiasedElements(mNotAADragBackup);
12573 mParentPlot->setNotAntialiasedElements(mNotAADragBackup);
12582 }
12574 }
12583 }
12575 }
12584
12576
@@ -12598,26 +12590,26 void QCPAxisRect::mouseReleaseEvent(QMou
12598 */
12590 */
12599 void QCPAxisRect::wheelEvent(QWheelEvent *event)
12591 void QCPAxisRect::wheelEvent(QWheelEvent *event)
12600 {
12592 {
12601 // Mouse range zooming interaction:
12593 // Mouse range zooming interaction:
12602 if (mParentPlot->interactions().testFlag(QCP::iRangeZoom))
12594 if (mParentPlot->interactions().testFlag(QCP::iRangeZoom))
12603 {
12595 {
12604 if (mRangeZoom != 0)
12596 if (mRangeZoom != 0)
12605 {
12597 {
12606 double factor;
12598 double factor;
12607 double wheelSteps = event->delta()/120.0; // a single step delta is +/-120 usually
12599 double wheelSteps = event->delta()/120.0; // a single step delta is +/-120 usually
12608 if (mRangeZoom.testFlag(Qt::Horizontal))
12600 if (mRangeZoom.testFlag(Qt::Horizontal))
12609 {
12601 {
12610 factor = qPow(mRangeZoomFactorHorz, wheelSteps);
12602 factor = qPow(mRangeZoomFactorHorz, wheelSteps);
12611 if (mRangeZoomHorzAxis.data())
12603 if (mRangeZoomHorzAxis.data())
12612 mRangeZoomHorzAxis.data()->scaleRange(factor, mRangeZoomHorzAxis.data()->pixelToCoord(event->pos().x()));
12604 mRangeZoomHorzAxis.data()->scaleRange(factor, mRangeZoomHorzAxis.data()->pixelToCoord(event->pos().x()));
12613 }
12605 }
12614 if (mRangeZoom.testFlag(Qt::Vertical))
12606 if (mRangeZoom.testFlag(Qt::Vertical))
12615 {
12607 {
12616 factor = qPow(mRangeZoomFactorVert, wheelSteps);
12608 factor = qPow(mRangeZoomFactorVert, wheelSteps);
12617 if (mRangeZoomVertAxis.data())
12609 if (mRangeZoomVertAxis.data())
12618 mRangeZoomVertAxis.data()->scaleRange(factor, mRangeZoomVertAxis.data()->pixelToCoord(event->pos().y()));
12610 mRangeZoomVertAxis.data()->scaleRange(factor, mRangeZoomVertAxis.data()->pixelToCoord(event->pos().y()));
12619 }
12611 }
12620 mParentPlot->replot();
12612 mParentPlot->replot();
12621 }
12613 }
12622 }
12614 }
12623 }
12615 }
@@ -12666,17 +12658,17 void QCPAxisRect::wheelEvent(QWheelEvent
12666 cause the item to be added to \a parent, so \ref QCPLegend::addItem must be called separately.
12658 cause the item to be added to \a parent, so \ref QCPLegend::addItem must be called separately.
12667 */
12659 */
12668 QCPAbstractLegendItem::QCPAbstractLegendItem(QCPLegend *parent) :
12660 QCPAbstractLegendItem::QCPAbstractLegendItem(QCPLegend *parent) :
12669 QCPLayoutElement(parent->parentPlot()),
12661 QCPLayoutElement(parent->parentPlot()),
12670 mParentLegend(parent),
12662 mParentLegend(parent),
12671 mFont(parent->font()),
12663 mFont(parent->font()),
12672 mTextColor(parent->textColor()),
12664 mTextColor(parent->textColor()),
12673 mSelectedFont(parent->selectedFont()),
12665 mSelectedFont(parent->selectedFont()),
12674 mSelectedTextColor(parent->selectedTextColor()),
12666 mSelectedTextColor(parent->selectedTextColor()),
12675 mSelectable(true),
12667 mSelectable(true),
12676 mSelected(false)
12668 mSelected(false)
12677 {
12669 {
12678 setLayer(QLatin1String("legend"));
12670 setLayer(QLatin1String("legend"));
12679 setMargins(QMargins(8, 2, 8, 2));
12671 setMargins(QMargins(8, 2, 8, 2));
12680 }
12672 }
12681
12673
12682 /*!
12674 /*!
@@ -12686,7 +12678,7 QCPAbstractLegendItem::QCPAbstractLegend
12686 */
12678 */
12687 void QCPAbstractLegendItem::setFont(const QFont &font)
12679 void QCPAbstractLegendItem::setFont(const QFont &font)
12688 {
12680 {
12689 mFont = font;
12681 mFont = font;
12690 }
12682 }
12691
12683
12692 /*!
12684 /*!
@@ -12696,7 +12688,7 void QCPAbstractLegendItem::setFont(cons
12696 */
12688 */
12697 void QCPAbstractLegendItem::setTextColor(const QColor &color)
12689 void QCPAbstractLegendItem::setTextColor(const QColor &color)
12698 {
12690 {
12699 mTextColor = color;
12691 mTextColor = color;
12700 }
12692 }
12701
12693
12702 /*!
12694 /*!
@@ -12707,7 +12699,7 void QCPAbstractLegendItem::setTextColor
12707 */
12699 */
12708 void QCPAbstractLegendItem::setSelectedFont(const QFont &font)
12700 void QCPAbstractLegendItem::setSelectedFont(const QFont &font)
12709 {
12701 {
12710 mSelectedFont = font;
12702 mSelectedFont = font;
12711 }
12703 }
12712
12704
12713 /*!
12705 /*!
@@ -12718,7 +12710,7 void QCPAbstractLegendItem::setSelectedF
12718 */
12710 */
12719 void QCPAbstractLegendItem::setSelectedTextColor(const QColor &color)
12711 void QCPAbstractLegendItem::setSelectedTextColor(const QColor &color)
12720 {
12712 {
12721 mSelectedTextColor = color;
12713 mSelectedTextColor = color;
12722 }
12714 }
12723
12715
12724 /*!
12716 /*!
@@ -12728,10 +12720,10 void QCPAbstractLegendItem::setSelectedT
12728 */
12720 */
12729 void QCPAbstractLegendItem::setSelectable(bool selectable)
12721 void QCPAbstractLegendItem::setSelectable(bool selectable)
12730 {
12722 {
12731 if (mSelectable != selectable)
12723 if (mSelectable != selectable)
12732 {
12724 {
12733 mSelectable = selectable;
12725 mSelectable = selectable;
12734 emit selectableChanged(mSelectable);
12726 emit selectableChanged(mSelectable);
12735 }
12727 }
12736 }
12728 }
12737
12729
@@ -12745,62 +12737,62 void QCPAbstractLegendItem::setSelectabl
12745 */
12737 */
12746 void QCPAbstractLegendItem::setSelected(bool selected)
12738 void QCPAbstractLegendItem::setSelected(bool selected)
12747 {
12739 {
12748 if (mSelected != selected)
12740 if (mSelected != selected)
12749 {
12741 {
12750 mSelected = selected;
12742 mSelected = selected;
12751 emit selectionChanged(mSelected);
12743 emit selectionChanged(mSelected);
12752 }
12744 }
12753 }
12745 }
12754
12746
12755 /* inherits documentation from base class */
12747 /* inherits documentation from base class */
12756 double QCPAbstractLegendItem::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
12748 double QCPAbstractLegendItem::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
12757 {
12749 {
12758 Q_UNUSED(details)
12750 Q_UNUSED(details)
12759 if (!mParentPlot) return -1;
12751 if (!mParentPlot) return -1;
12760 if (onlySelectable && (!mSelectable || !mParentLegend->selectableParts().testFlag(QCPLegend::spItems)))
12752 if (onlySelectable && (!mSelectable || !mParentLegend->selectableParts().testFlag(QCPLegend::spItems)))
12761 return -1;
12753 return -1;
12762
12754
12763 if (mRect.contains(pos.toPoint()))
12755 if (mRect.contains(pos.toPoint()))
12764 return mParentPlot->selectionTolerance()*0.99;
12756 return mParentPlot->selectionTolerance()*0.99;
12765 else
12757 else
12766 return -1;
12758 return -1;
12767 }
12759 }
12768
12760
12769 /* inherits documentation from base class */
12761 /* inherits documentation from base class */
12770 void QCPAbstractLegendItem::applyDefaultAntialiasingHint(QCPPainter *painter) const
12762 void QCPAbstractLegendItem::applyDefaultAntialiasingHint(QCPPainter *painter) const
12771 {
12763 {
12772 applyAntialiasingHint(painter, mAntialiased, QCP::aeLegendItems);
12764 applyAntialiasingHint(painter, mAntialiased, QCP::aeLegendItems);
12773 }
12765 }
12774
12766
12775 /* inherits documentation from base class */
12767 /* inherits documentation from base class */
12776 QRect QCPAbstractLegendItem::clipRect() const
12768 QRect QCPAbstractLegendItem::clipRect() const
12777 {
12769 {
12778 return mOuterRect;
12770 return mOuterRect;
12779 }
12771 }
12780
12772
12781 /* inherits documentation from base class */
12773 /* inherits documentation from base class */
12782 void QCPAbstractLegendItem::selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged)
12774 void QCPAbstractLegendItem::selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged)
12783 {
12775 {
12784 Q_UNUSED(event)
12776 Q_UNUSED(event)
12785 Q_UNUSED(details)
12777 Q_UNUSED(details)
12786 if (mSelectable && mParentLegend->selectableParts().testFlag(QCPLegend::spItems))
12778 if (mSelectable && mParentLegend->selectableParts().testFlag(QCPLegend::spItems))
12787 {
12779 {
12788 bool selBefore = mSelected;
12780 bool selBefore = mSelected;
12789 setSelected(additive ? !mSelected : true);
12781 setSelected(additive ? !mSelected : true);
12790 if (selectionStateChanged)
12782 if (selectionStateChanged)
12791 *selectionStateChanged = mSelected != selBefore;
12783 *selectionStateChanged = mSelected != selBefore;
12792 }
12784 }
12793 }
12785 }
12794
12786
12795 /* inherits documentation from base class */
12787 /* inherits documentation from base class */
12796 void QCPAbstractLegendItem::deselectEvent(bool *selectionStateChanged)
12788 void QCPAbstractLegendItem::deselectEvent(bool *selectionStateChanged)
12797 {
12789 {
12798 if (mSelectable && mParentLegend->selectableParts().testFlag(QCPLegend::spItems))
12790 if (mSelectable && mParentLegend->selectableParts().testFlag(QCPLegend::spItems))
12799 {
12791 {
12800 bool selBefore = mSelected;
12792 bool selBefore = mSelected;
12801 setSelected(false);
12793 setSelected(false);
12802 if (selectionStateChanged)
12794 if (selectionStateChanged)
12803 *selectionStateChanged = mSelected != selBefore;
12795 *selectionStateChanged = mSelected != selBefore;
12804 }
12796 }
12805 }
12797 }
12806
12798
@@ -12842,8 +12834,8 void QCPAbstractLegendItem::deselectEven
12842 QCPAbstractPlottable::addToLegend and \ref QCPAbstractPlottable::removeFromLegend.
12834 QCPAbstractPlottable::addToLegend and \ref QCPAbstractPlottable::removeFromLegend.
12843 */
12835 */
12844 QCPPlottableLegendItem::QCPPlottableLegendItem(QCPLegend *parent, QCPAbstractPlottable *plottable) :
12836 QCPPlottableLegendItem::QCPPlottableLegendItem(QCPLegend *parent, QCPAbstractPlottable *plottable) :
12845 QCPAbstractLegendItem(parent),
12837 QCPAbstractLegendItem(parent),
12846 mPlottable(plottable)
12838 mPlottable(plottable)
12847 {
12839 {
12848 }
12840 }
12849
12841
@@ -12854,7 +12846,7 QCPPlottableLegendItem::QCPPlottableLege
12854 */
12846 */
12855 QPen QCPPlottableLegendItem::getIconBorderPen() const
12847 QPen QCPPlottableLegendItem::getIconBorderPen() const
12856 {
12848 {
12857 return mSelected ? mParentLegend->selectedIconBorderPen() : mParentLegend->iconBorderPen();
12849 return mSelected ? mParentLegend->selectedIconBorderPen() : mParentLegend->iconBorderPen();
12858 }
12850 }
12859
12851
12860 /*! \internal
12852 /*! \internal
@@ -12864,7 +12856,7 QPen QCPPlottableLegendItem::getIconBord
12864 */
12856 */
12865 QColor QCPPlottableLegendItem::getTextColor() const
12857 QColor QCPPlottableLegendItem::getTextColor() const
12866 {
12858 {
12867 return mSelected ? mSelectedTextColor : mTextColor;
12859 return mSelected ? mSelectedTextColor : mTextColor;
12868 }
12860 }
12869
12861
12870 /*! \internal
12862 /*! \internal
@@ -12874,7 +12866,7 QColor QCPPlottableLegendItem::getTextCo
12874 */
12866 */
12875 QFont QCPPlottableLegendItem::getFont() const
12867 QFont QCPPlottableLegendItem::getFont() const
12876 {
12868 {
12877 return mSelected ? mSelectedFont : mFont;
12869 return mSelected ? mSelectedFont : mFont;
12878 }
12870 }
12879
12871
12880 /*! \internal
12872 /*! \internal
@@ -12885,25 +12877,25 QFont QCPPlottableLegendItem::getFont()
12885 */
12877 */
12886 void QCPPlottableLegendItem::draw(QCPPainter *painter)
12878 void QCPPlottableLegendItem::draw(QCPPainter *painter)
12887 {
12879 {
12888 if (!mPlottable) return;
12880 if (!mPlottable) return;
12889 painter->setFont(getFont());
12881 painter->setFont(getFont());
12890 painter->setPen(QPen(getTextColor()));
12882 painter->setPen(QPen(getTextColor()));
12891 QSizeF iconSize = mParentLegend->iconSize();
12883 QSizeF iconSize = mParentLegend->iconSize();
12892 QRectF textRect = painter->fontMetrics().boundingRect(0, 0, 0, iconSize.height(), Qt::TextDontClip, mPlottable->name());
12884 QRectF textRect = painter->fontMetrics().boundingRect(0, 0, 0, iconSize.height(), Qt::TextDontClip, mPlottable->name());
12893 QRectF iconRect(mRect.topLeft(), iconSize);
12885 QRectF iconRect(mRect.topLeft(), iconSize);
12894 int textHeight = qMax(textRect.height(), iconSize.height()); // if text has smaller height than icon, center text vertically in icon height, else align tops
12886 int textHeight = qMax(textRect.height(), iconSize.height()); // if text has smaller height than icon, center text vertically in icon height, else align tops
12895 painter->drawText(mRect.x()+iconSize.width()+mParentLegend->iconTextPadding(), mRect.y(), textRect.width(), textHeight, Qt::TextDontClip, mPlottable->name());
12887 painter->drawText(mRect.x()+iconSize.width()+mParentLegend->iconTextPadding(), mRect.y(), textRect.width(), textHeight, Qt::TextDontClip, mPlottable->name());
12896 // draw icon:
12888 // draw icon:
12897 painter->save();
12889 painter->save();
12898 painter->setClipRect(iconRect, Qt::IntersectClip);
12890 painter->setClipRect(iconRect, Qt::IntersectClip);
12899 mPlottable->drawLegendIcon(painter, iconRect);
12891 mPlottable->drawLegendIcon(painter, iconRect);
12900 painter->restore();
12892 painter->restore();
12901 // draw icon border:
12893 // draw icon border:
12902 if (getIconBorderPen().style() != Qt::NoPen)
12894 if (getIconBorderPen().style() != Qt::NoPen)
12903 {
12895 {
12904 painter->setPen(getIconBorderPen());
12896 painter->setPen(getIconBorderPen());
12905 painter->setBrush(Qt::NoBrush);
12897 painter->setBrush(Qt::NoBrush);
12906 painter->drawRect(iconRect);
12898 painter->drawRect(iconRect);
12907 }
12899 }
12908 }
12900 }
12909
12901
@@ -12914,15 +12906,15 void QCPPlottableLegendItem::draw(QCPPai
12914 */
12906 */
12915 QSize QCPPlottableLegendItem::minimumSizeHint() const
12907 QSize QCPPlottableLegendItem::minimumSizeHint() const
12916 {
12908 {
12917 if (!mPlottable) return QSize();
12909 if (!mPlottable) return QSize();
12918 QSize result(0, 0);
12910 QSize result(0, 0);
12919 QRect textRect;
12911 QRect textRect;
12920 QFontMetrics fontMetrics(getFont());
12912 QFontMetrics fontMetrics(getFont());
12921 QSize iconSize = mParentLegend->iconSize();
12913 QSize iconSize = mParentLegend->iconSize();
12922 textRect = fontMetrics.boundingRect(0, 0, 0, iconSize.height(), Qt::TextDontClip, mPlottable->name());
12914 textRect = fontMetrics.boundingRect(0, 0, 0, iconSize.height(), Qt::TextDontClip, mPlottable->name());
12923 result.setWidth(iconSize.width() + mParentLegend->iconTextPadding() + textRect.width() + mMargins.left() + mMargins.right());
12915 result.setWidth(iconSize.width() + mParentLegend->iconTextPadding() + textRect.width() + mMargins.left() + mMargins.right());
12924 result.setHeight(qMax(textRect.height(), iconSize.height()) + mMargins.top() + mMargins.bottom());
12916 result.setHeight(qMax(textRect.height(), iconSize.height()) + mMargins.top() + mMargins.bottom());
12925 return result;
12917 return result;
12926 }
12918 }
12927
12919
12928
12920
@@ -12973,51 +12965,51 QSize QCPPlottableLegendItem::minimumSiz
12973 */
12965 */
12974 QCPLegend::QCPLegend()
12966 QCPLegend::QCPLegend()
12975 {
12967 {
12976 setRowSpacing(0);
12968 setRowSpacing(0);
12977 setColumnSpacing(10);
12969 setColumnSpacing(10);
12978 setMargins(QMargins(2, 3, 2, 2));
12970 setMargins(QMargins(2, 3, 2, 2));
12979 setAntialiased(false);
12971 setAntialiased(false);
12980 setIconSize(32, 18);
12972 setIconSize(32, 18);
12981
12973
12982 setIconTextPadding(7);
12974 setIconTextPadding(7);
12983
12975
12984 setSelectableParts(spLegendBox | spItems);
12976 setSelectableParts(spLegendBox | spItems);
12985 setSelectedParts(spNone);
12977 setSelectedParts(spNone);
12986
12978
12987 setBorderPen(QPen(Qt::black));
12979 setBorderPen(QPen(Qt::black));
12988 setSelectedBorderPen(QPen(Qt::blue, 2));
12980 setSelectedBorderPen(QPen(Qt::blue, 2));
12989 setIconBorderPen(Qt::NoPen);
12981 setIconBorderPen(Qt::NoPen);
12990 setSelectedIconBorderPen(QPen(Qt::blue, 2));
12982 setSelectedIconBorderPen(QPen(Qt::blue, 2));
12991 setBrush(Qt::white);
12983 setBrush(Qt::white);
12992 setSelectedBrush(Qt::white);
12984 setSelectedBrush(Qt::white);
12993 setTextColor(Qt::black);
12985 setTextColor(Qt::black);
12994 setSelectedTextColor(Qt::blue);
12986 setSelectedTextColor(Qt::blue);
12995 }
12987 }
12996
12988
12997 QCPLegend::~QCPLegend()
12989 QCPLegend::~QCPLegend()
12998 {
12990 {
12999 clearItems();
12991 clearItems();
13000 if (qobject_cast<QCustomPlot*>(mParentPlot)) // make sure this isn't called from QObject dtor when QCustomPlot is already destructed (happens when the legend is not in any layout and thus QObject-child of QCustomPlot)
12992 if (qobject_cast<QCustomPlot*>(mParentPlot)) // make sure this isn't called from QObject dtor when QCustomPlot is already destructed (happens when the legend is not in any layout and thus QObject-child of QCustomPlot)
13001 mParentPlot->legendRemoved(this);
12993 mParentPlot->legendRemoved(this);
13002 }
12994 }
13003
12995
13004 /* no doc for getter, see setSelectedParts */
12996 /* no doc for getter, see setSelectedParts */
13005 QCPLegend::SelectableParts QCPLegend::selectedParts() const
12997 QCPLegend::SelectableParts QCPLegend::selectedParts() const
13006 {
12998 {
13007 // check whether any legend elements selected, if yes, add spItems to return value
12999 // check whether any legend elements selected, if yes, add spItems to return value
13008 bool hasSelectedItems = false;
13000 bool hasSelectedItems = false;
13009 for (int i=0; i<itemCount(); ++i)
13001 for (int i=0; i<itemCount(); ++i)
13010 {
13002 {
13011 if (item(i) && item(i)->selected())
13003 if (item(i) && item(i)->selected())
13012 {
13004 {
13013 hasSelectedItems = true;
13005 hasSelectedItems = true;
13014 break;
13006 break;
13015 }
13007 }
13016 }
13008 }
13017 if (hasSelectedItems)
13009 if (hasSelectedItems)
13018 return mSelectedParts | spItems;
13010 return mSelectedParts | spItems;
13019 else
13011 else
13020 return mSelectedParts & ~spItems;
13012 return mSelectedParts & ~spItems;
13021 }
13013 }
13022
13014
13023 /*!
13015 /*!
@@ -13025,7 +13017,7 QCPLegend::SelectableParts QCPLegend::se
13025 */
13017 */
13026 void QCPLegend::setBorderPen(const QPen &pen)
13018 void QCPLegend::setBorderPen(const QPen &pen)
13027 {
13019 {
13028 mBorderPen = pen;
13020 mBorderPen = pen;
13029 }
13021 }
13030
13022
13031 /*!
13023 /*!
@@ -13033,7 +13025,7 void QCPLegend::setBorderPen(const QPen
13033 */
13025 */
13034 void QCPLegend::setBrush(const QBrush &brush)
13026 void QCPLegend::setBrush(const QBrush &brush)
13035 {
13027 {
13036 mBrush = brush;
13028 mBrush = brush;
13037 }
13029 }
13038
13030
13039 /*!
13031 /*!
@@ -13047,11 +13039,11 void QCPLegend::setBrush(const QBrush &b
13047 */
13039 */
13048 void QCPLegend::setFont(const QFont &font)
13040 void QCPLegend::setFont(const QFont &font)
13049 {
13041 {
13050 mFont = font;
13042 mFont = font;
13051 for (int i=0; i<itemCount(); ++i)
13043 for (int i=0; i<itemCount(); ++i)
13052 {
13044 {
13053 if (item(i))
13045 if (item(i))
13054 item(i)->setFont(mFont);
13046 item(i)->setFont(mFont);
13055 }
13047 }
13056 }
13048 }
13057
13049
@@ -13066,11 +13058,11 void QCPLegend::setFont(const QFont &fon
13066 */
13058 */
13067 void QCPLegend::setTextColor(const QColor &color)
13059 void QCPLegend::setTextColor(const QColor &color)
13068 {
13060 {
13069 mTextColor = color;
13061 mTextColor = color;
13070 for (int i=0; i<itemCount(); ++i)
13062 for (int i=0; i<itemCount(); ++i)
13071 {
13063 {
13072 if (item(i))
13064 if (item(i))
13073 item(i)->setTextColor(color);
13065 item(i)->setTextColor(color);
13074 }
13066 }
13075 }
13067 }
13076
13068
@@ -13080,15 +13072,15 void QCPLegend::setTextColor(const QColo
13080 */
13072 */
13081 void QCPLegend::setIconSize(const QSize &size)
13073 void QCPLegend::setIconSize(const QSize &size)
13082 {
13074 {
13083 mIconSize = size;
13075 mIconSize = size;
13084 }
13076 }
13085
13077
13086 /*! \overload
13078 /*! \overload
13087 */
13079 */
13088 void QCPLegend::setIconSize(int width, int height)
13080 void QCPLegend::setIconSize(int width, int height)
13089 {
13081 {
13090 mIconSize.setWidth(width);
13082 mIconSize.setWidth(width);
13091 mIconSize.setHeight(height);
13083 mIconSize.setHeight(height);
13092 }
13084 }
13093
13085
13094 /*!
13086 /*!
@@ -13098,7 +13090,7 void QCPLegend::setIconSize(int width, i
13098 */
13090 */
13099 void QCPLegend::setIconTextPadding(int padding)
13091 void QCPLegend::setIconTextPadding(int padding)
13100 {
13092 {
13101 mIconTextPadding = padding;
13093 mIconTextPadding = padding;
13102 }
13094 }
13103
13095
13104 /*!
13096 /*!
@@ -13109,7 +13101,7 void QCPLegend::setIconTextPadding(int p
13109 */
13101 */
13110 void QCPLegend::setIconBorderPen(const QPen &pen)
13102 void QCPLegend::setIconBorderPen(const QPen &pen)
13111 {
13103 {
13112 mIconBorderPen = pen;
13104 mIconBorderPen = pen;
13113 }
13105 }
13114
13106
13115 /*!
13107 /*!
@@ -13124,10 +13116,10 void QCPLegend::setIconBorderPen(const Q
13124 */
13116 */
13125 void QCPLegend::setSelectableParts(const SelectableParts &selectable)
13117 void QCPLegend::setSelectableParts(const SelectableParts &selectable)
13126 {
13118 {
13127 if (mSelectableParts != selectable)
13119 if (mSelectableParts != selectable)
13128 {
13120 {
13129 mSelectableParts = selectable;
13121 mSelectableParts = selectable;
13130 emit selectableChanged(mSelectableParts);
13122 emit selectableChanged(mSelectableParts);
13131 }
13123 }
13132 }
13124 }
13133
13125
@@ -13154,26 +13146,26 void QCPLegend::setSelectableParts(const
13154 */
13146 */
13155 void QCPLegend::setSelectedParts(const SelectableParts &selected)
13147 void QCPLegend::setSelectedParts(const SelectableParts &selected)
13156 {
13148 {
13157 SelectableParts newSelected = selected;
13149 SelectableParts newSelected = selected;
13158 mSelectedParts = this->selectedParts(); // update mSelectedParts in case item selection changed
13150 mSelectedParts = this->selectedParts(); // update mSelectedParts in case item selection changed
13159
13151
13160 if (mSelectedParts != newSelected)
13152 if (mSelectedParts != newSelected)
13161 {
13153 {
13162 if (!mSelectedParts.testFlag(spItems) && newSelected.testFlag(spItems)) // attempt to set spItems flag (can't do that)
13154 if (!mSelectedParts.testFlag(spItems) && newSelected.testFlag(spItems)) // attempt to set spItems flag (can't do that)
13163 {
13155 {
13164 qDebug() << Q_FUNC_INFO << "spItems flag can not be set, it can only be unset with this function";
13156 qDebug() << Q_FUNC_INFO << "spItems flag can not be set, it can only be unset with this function";
13165 newSelected &= ~spItems;
13157 newSelected &= ~spItems;
13166 }
13158 }
13167 if (mSelectedParts.testFlag(spItems) && !newSelected.testFlag(spItems)) // spItems flag was unset, so clear item selection
13159 if (mSelectedParts.testFlag(spItems) && !newSelected.testFlag(spItems)) // spItems flag was unset, so clear item selection
13168 {
13160 {
13169 for (int i=0; i<itemCount(); ++i)
13161 for (int i=0; i<itemCount(); ++i)
13170 {
13162 {
13171 if (item(i))
13163 if (item(i))
13172 item(i)->setSelected(false);
13164 item(i)->setSelected(false);
13173 }
13165 }
13174 }
13166 }
13175 mSelectedParts = newSelected;
13167 mSelectedParts = newSelected;
13176 emit selectionChanged(mSelectedParts);
13168 emit selectionChanged(mSelectedParts);
13177 }
13169 }
13178 }
13170 }
13179
13171
@@ -13185,7 +13177,7 void QCPLegend::setSelectedParts(const S
13185 */
13177 */
13186 void QCPLegend::setSelectedBorderPen(const QPen &pen)
13178 void QCPLegend::setSelectedBorderPen(const QPen &pen)
13187 {
13179 {
13188 mSelectedBorderPen = pen;
13180 mSelectedBorderPen = pen;
13189 }
13181 }
13190
13182
13191 /*!
13183 /*!
@@ -13195,7 +13187,7 void QCPLegend::setSelectedBorderPen(con
13195 */
13187 */
13196 void QCPLegend::setSelectedIconBorderPen(const QPen &pen)
13188 void QCPLegend::setSelectedIconBorderPen(const QPen &pen)
13197 {
13189 {
13198 mSelectedIconBorderPen = pen;
13190 mSelectedIconBorderPen = pen;
13199 }
13191 }
13200
13192
13201 /*!
13193 /*!
@@ -13206,7 +13198,7 void QCPLegend::setSelectedIconBorderPen
13206 */
13198 */
13207 void QCPLegend::setSelectedBrush(const QBrush &brush)
13199 void QCPLegend::setSelectedBrush(const QBrush &brush)
13208 {
13200 {
13209 mSelectedBrush = brush;
13201 mSelectedBrush = brush;
13210 }
13202 }
13211
13203
13212 /*!
13204 /*!
@@ -13218,11 +13210,11 void QCPLegend::setSelectedBrush(const Q
13218 */
13210 */
13219 void QCPLegend::setSelectedFont(const QFont &font)
13211 void QCPLegend::setSelectedFont(const QFont &font)
13220 {
13212 {
13221 mSelectedFont = font;
13213 mSelectedFont = font;
13222 for (int i=0; i<itemCount(); ++i)
13214 for (int i=0; i<itemCount(); ++i)
13223 {
13215 {
13224 if (item(i))
13216 if (item(i))
13225 item(i)->setSelectedFont(font);
13217 item(i)->setSelectedFont(font);
13226 }
13218 }
13227 }
13219 }
13228
13220
@@ -13235,11 +13227,11 void QCPLegend::setSelectedFont(const QF
13235 */
13227 */
13236 void QCPLegend::setSelectedTextColor(const QColor &color)
13228 void QCPLegend::setSelectedTextColor(const QColor &color)
13237 {
13229 {
13238 mSelectedTextColor = color;
13230 mSelectedTextColor = color;
13239 for (int i=0; i<itemCount(); ++i)
13231 for (int i=0; i<itemCount(); ++i)
13240 {
13232 {
13241 if (item(i))
13233 if (item(i))
13242 item(i)->setSelectedTextColor(color);
13234 item(i)->setSelectedTextColor(color);
13243 }
13235 }
13244 }
13236 }
13245
13237
@@ -13250,7 +13242,7 void QCPLegend::setSelectedTextColor(con
13250 */
13242 */
13251 QCPAbstractLegendItem *QCPLegend::item(int index) const
13243 QCPAbstractLegendItem *QCPLegend::item(int index) const
13252 {
13244 {
13253 return qobject_cast<QCPAbstractLegendItem*>(elementAt(index));
13245 return qobject_cast<QCPAbstractLegendItem*>(elementAt(index));
13254 }
13246 }
13255
13247
13256 /*!
13248 /*!
@@ -13261,15 +13253,15 QCPAbstractLegendItem *QCPLegend::item(i
13261 */
13253 */
13262 QCPPlottableLegendItem *QCPLegend::itemWithPlottable(const QCPAbstractPlottable *plottable) const
13254 QCPPlottableLegendItem *QCPLegend::itemWithPlottable(const QCPAbstractPlottable *plottable) const
13263 {
13255 {
13264 for (int i=0; i<itemCount(); ++i)
13256 for (int i=0; i<itemCount(); ++i)
13265 {
13257 {
13266 if (QCPPlottableLegendItem *pli = qobject_cast<QCPPlottableLegendItem*>(item(i)))
13258 if (QCPPlottableLegendItem *pli = qobject_cast<QCPPlottableLegendItem*>(item(i)))
13267 {
13259 {
13268 if (pli->plottable() == plottable)
13260 if (pli->plottable() == plottable)
13269 return pli;
13261 return pli;
13270 }
13262 }
13271 }
13263 }
13272 return 0;
13264 return 0;
13273 }
13265 }
13274
13266
13275 /*!
13267 /*!
@@ -13278,7 +13270,7 QCPPlottableLegendItem *QCPLegend::itemW
13278 */
13270 */
13279 int QCPLegend::itemCount() const
13271 int QCPLegend::itemCount() const
13280 {
13272 {
13281 return elementCount();
13273 return elementCount();
13282 }
13274 }
13283
13275
13284 /*!
13276 /*!
@@ -13286,12 +13278,12 int QCPLegend::itemCount() const
13286 */
13278 */
13287 bool QCPLegend::hasItem(QCPAbstractLegendItem *item) const
13279 bool QCPLegend::hasItem(QCPAbstractLegendItem *item) const
13288 {
13280 {
13289 for (int i=0; i<itemCount(); ++i)
13281 for (int i=0; i<itemCount(); ++i)
13290 {
13282 {
13291 if (item == this->item(i))
13283 if (item == this->item(i))
13292 return true;
13284 return true;
13293 }
13285 }
13294 return false;
13286 return false;
13295 }
13287 }
13296
13288
13297 /*!
13289 /*!
@@ -13302,7 +13294,7 bool QCPLegend::hasItem(QCPAbstractLegen
13302 */
13294 */
13303 bool QCPLegend::hasItemWithPlottable(const QCPAbstractPlottable *plottable) const
13295 bool QCPLegend::hasItemWithPlottable(const QCPAbstractPlottable *plottable) const
13304 {
13296 {
13305 return itemWithPlottable(plottable);
13297 return itemWithPlottable(plottable);
13306 }
13298 }
13307
13299
13308 /*!
13300 /*!
@@ -13314,11 +13306,11 bool QCPLegend::hasItemWithPlottable(con
13314 */
13306 */
13315 bool QCPLegend::addItem(QCPAbstractLegendItem *item)
13307 bool QCPLegend::addItem(QCPAbstractLegendItem *item)
13316 {
13308 {
13317 if (!hasItem(item))
13309 if (!hasItem(item))
13318 {
13310 {
13319 return addElement(rowCount(), 0, item);
13311 return addElement(rowCount(), 0, item);
13320 } else
13312 } else
13321 return false;
13313 return false;
13322 }
13314 }
13323
13315
13324 /*!
13316 /*!
@@ -13330,13 +13322,13 bool QCPLegend::addItem(QCPAbstractLegen
13330 */
13322 */
13331 bool QCPLegend::removeItem(int index)
13323 bool QCPLegend::removeItem(int index)
13332 {
13324 {
13333 if (QCPAbstractLegendItem *ali = item(index))
13325 if (QCPAbstractLegendItem *ali = item(index))
13334 {
13326 {
13335 bool success = remove(ali);
13327 bool success = remove(ali);
13336 simplify();
13328 simplify();
13337 return success;
13329 return success;
13338 } else
13330 } else
13339 return false;
13331 return false;
13340 }
13332 }
13341
13333
13342 /*! \overload
13334 /*! \overload
@@ -13349,9 +13341,9 bool QCPLegend::removeItem(int index)
13349 */
13341 */
13350 bool QCPLegend::removeItem(QCPAbstractLegendItem *item)
13342 bool QCPLegend::removeItem(QCPAbstractLegendItem *item)
13351 {
13343 {
13352 bool success = remove(item);
13344 bool success = remove(item);
13353 simplify();
13345 simplify();
13354 return success;
13346 return success;
13355 }
13347 }
13356
13348
13357 /*!
13349 /*!
@@ -13359,8 +13351,8 bool QCPLegend::removeItem(QCPAbstractLe
13359 */
13351 */
13360 void QCPLegend::clearItems()
13352 void QCPLegend::clearItems()
13361 {
13353 {
13362 for (int i=itemCount()-1; i>=0; --i)
13354 for (int i=itemCount()-1; i>=0; --i)
13363 removeItem(i);
13355 removeItem(i);
13364 }
13356 }
13365
13357
13366 /*!
13358 /*!
@@ -13371,16 +13363,16 void QCPLegend::clearItems()
13371 */
13363 */
13372 QList<QCPAbstractLegendItem *> QCPLegend::selectedItems() const
13364 QList<QCPAbstractLegendItem *> QCPLegend::selectedItems() const
13373 {
13365 {
13374 QList<QCPAbstractLegendItem*> result;
13366 QList<QCPAbstractLegendItem*> result;
13375 for (int i=0; i<itemCount(); ++i)
13367 for (int i=0; i<itemCount(); ++i)
13376 {
13368 {
13377 if (QCPAbstractLegendItem *ali = item(i))
13369 if (QCPAbstractLegendItem *ali = item(i))
13378 {
13370 {
13379 if (ali->selected())
13371 if (ali->selected())
13380 result.append(ali);
13372 result.append(ali);
13381 }
13373 }
13382 }
13374 }
13383 return result;
13375 return result;
13384 }
13376 }
13385
13377
13386 /*! \internal
13378 /*! \internal
@@ -13398,7 +13390,7 QList<QCPAbstractLegendItem *> QCPLegend
13398 */
13390 */
13399 void QCPLegend::applyDefaultAntialiasingHint(QCPPainter *painter) const
13391 void QCPLegend::applyDefaultAntialiasingHint(QCPPainter *painter) const
13400 {
13392 {
13401 applyAntialiasingHint(painter, mAntialiased, QCP::aeLegend);
13393 applyAntialiasingHint(painter, mAntialiased, QCP::aeLegend);
13402 }
13394 }
13403
13395
13404 /*! \internal
13396 /*! \internal
@@ -13408,7 +13400,7 void QCPLegend::applyDefaultAntialiasing
13408 */
13400 */
13409 QPen QCPLegend::getBorderPen() const
13401 QPen QCPLegend::getBorderPen() const
13410 {
13402 {
13411 return mSelectedParts.testFlag(spLegendBox) ? mSelectedBorderPen : mBorderPen;
13403 return mSelectedParts.testFlag(spLegendBox) ? mSelectedBorderPen : mBorderPen;
13412 }
13404 }
13413
13405
13414 /*! \internal
13406 /*! \internal
@@ -13418,7 +13410,7 QPen QCPLegend::getBorderPen() const
13418 */
13410 */
13419 QBrush QCPLegend::getBrush() const
13411 QBrush QCPLegend::getBrush() const
13420 {
13412 {
13421 return mSelectedParts.testFlag(spLegendBox) ? mSelectedBrush : mBrush;
13413 return mSelectedParts.testFlag(spLegendBox) ? mSelectedBrush : mBrush;
13422 }
13414 }
13423
13415
13424 /*! \internal
13416 /*! \internal
@@ -13428,70 +13420,70 QBrush QCPLegend::getBrush() const
13428 */
13420 */
13429 void QCPLegend::draw(QCPPainter *painter)
13421 void QCPLegend::draw(QCPPainter *painter)
13430 {
13422 {
13431 // draw background rect:
13423 // draw background rect:
13432 painter->setBrush(getBrush());
13424 painter->setBrush(getBrush());
13433 painter->setPen(getBorderPen());
13425 painter->setPen(getBorderPen());
13434 painter->drawRect(mOuterRect);
13426 painter->drawRect(mOuterRect);
13435 }
13427 }
13436
13428
13437 /* inherits documentation from base class */
13429 /* inherits documentation from base class */
13438 double QCPLegend::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
13430 double QCPLegend::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
13439 {
13431 {
13440 if (!mParentPlot) return -1;
13432 if (!mParentPlot) return -1;
13441 if (onlySelectable && !mSelectableParts.testFlag(spLegendBox))
13433 if (onlySelectable && !mSelectableParts.testFlag(spLegendBox))
13434 return -1;
13435
13436 if (mOuterRect.contains(pos.toPoint()))
13437 {
13438 if (details) details->setValue(spLegendBox);
13439 return mParentPlot->selectionTolerance()*0.99;
13440 }
13442 return -1;
13441 return -1;
13443
13444 if (mOuterRect.contains(pos.toPoint()))
13445 {
13446 if (details) details->setValue(spLegendBox);
13447 return mParentPlot->selectionTolerance()*0.99;
13448 }
13449 return -1;
13450 }
13442 }
13451
13443
13452 /* inherits documentation from base class */
13444 /* inherits documentation from base class */
13453 void QCPLegend::selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged)
13445 void QCPLegend::selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged)
13454 {
13446 {
13455 Q_UNUSED(event)
13447 Q_UNUSED(event)
13456 mSelectedParts = selectedParts(); // in case item selection has changed
13448 mSelectedParts = selectedParts(); // in case item selection has changed
13457 if (details.value<SelectablePart>() == spLegendBox && mSelectableParts.testFlag(spLegendBox))
13449 if (details.value<SelectablePart>() == spLegendBox && mSelectableParts.testFlag(spLegendBox))
13458 {
13450 {
13459 SelectableParts selBefore = mSelectedParts;
13451 SelectableParts selBefore = mSelectedParts;
13460 setSelectedParts(additive ? mSelectedParts^spLegendBox : mSelectedParts|spLegendBox); // no need to unset spItems in !additive case, because they will be deselected by QCustomPlot (they're normal QCPLayerables with own deselectEvent)
13452 setSelectedParts(additive ? mSelectedParts^spLegendBox : mSelectedParts|spLegendBox); // no need to unset spItems in !additive case, because they will be deselected by QCustomPlot (they're normal QCPLayerables with own deselectEvent)
13461 if (selectionStateChanged)
13453 if (selectionStateChanged)
13462 *selectionStateChanged = mSelectedParts != selBefore;
13454 *selectionStateChanged = mSelectedParts != selBefore;
13463 }
13455 }
13464 }
13456 }
13465
13457
13466 /* inherits documentation from base class */
13458 /* inherits documentation from base class */
13467 void QCPLegend::deselectEvent(bool *selectionStateChanged)
13459 void QCPLegend::deselectEvent(bool *selectionStateChanged)
13468 {
13460 {
13469 mSelectedParts = selectedParts(); // in case item selection has changed
13461 mSelectedParts = selectedParts(); // in case item selection has changed
13470 if (mSelectableParts.testFlag(spLegendBox))
13462 if (mSelectableParts.testFlag(spLegendBox))
13471 {
13463 {
13472 SelectableParts selBefore = mSelectedParts;
13464 SelectableParts selBefore = mSelectedParts;
13473 setSelectedParts(selectedParts() & ~spLegendBox);
13465 setSelectedParts(selectedParts() & ~spLegendBox);
13474 if (selectionStateChanged)
13466 if (selectionStateChanged)
13475 *selectionStateChanged = mSelectedParts != selBefore;
13467 *selectionStateChanged = mSelectedParts != selBefore;
13476 }
13468 }
13477 }
13469 }
13478
13470
13479 /* inherits documentation from base class */
13471 /* inherits documentation from base class */
13480 QCP::Interaction QCPLegend::selectionCategory() const
13472 QCP::Interaction QCPLegend::selectionCategory() const
13481 {
13473 {
13482 return QCP::iSelectLegend;
13474 return QCP::iSelectLegend;
13483 }
13475 }
13484
13476
13485 /* inherits documentation from base class */
13477 /* inherits documentation from base class */
13486 QCP::Interaction QCPAbstractLegendItem::selectionCategory() const
13478 QCP::Interaction QCPAbstractLegendItem::selectionCategory() const
13487 {
13479 {
13488 return QCP::iSelectLegend;
13480 return QCP::iSelectLegend;
13489 }
13481 }
13490
13482
13491 /* inherits documentation from base class */
13483 /* inherits documentation from base class */
13492 void QCPLegend::parentPlotInitialized(QCustomPlot *parentPlot)
13484 void QCPLegend::parentPlotInitialized(QCustomPlot *parentPlot)
13493 {
13485 {
13494 Q_UNUSED(parentPlot)
13486 Q_UNUSED(parentPlot)
13495 }
13487 }
13496
13488
13497
13489
@@ -13535,21 +13527,21 void QCPLegend::parentPlotInitialized(QC
13535 To set the title text in the constructor, rather use \ref QCPPlotTitle(QCustomPlot *parentPlot, const QString &text).
13527 To set the title text in the constructor, rather use \ref QCPPlotTitle(QCustomPlot *parentPlot, const QString &text).
13536 */
13528 */
13537 QCPPlotTitle::QCPPlotTitle(QCustomPlot *parentPlot) :
13529 QCPPlotTitle::QCPPlotTitle(QCustomPlot *parentPlot) :
13538 QCPLayoutElement(parentPlot),
13530 QCPLayoutElement(parentPlot),
13539 mFont(QFont(QLatin1String("sans serif"), 13*1.5, QFont::Bold)),
13531 mFont(QFont(QLatin1String("sans serif"), 13*1.5, QFont::Bold)),
13540 mTextColor(Qt::black),
13532 mTextColor(Qt::black),
13541 mSelectedFont(QFont(QLatin1String("sans serif"), 13*1.6, QFont::Bold)),
13533 mSelectedFont(QFont(QLatin1String("sans serif"), 13*1.6, QFont::Bold)),
13542 mSelectedTextColor(Qt::blue),
13534 mSelectedTextColor(Qt::blue),
13543 mSelectable(false),
13535 mSelectable(false),
13544 mSelected(false)
13536 mSelected(false)
13545 {
13537 {
13546 if (parentPlot)
13538 if (parentPlot)
13547 {
13539 {
13548 setLayer(parentPlot->currentLayer());
13540 setLayer(parentPlot->currentLayer());
13549 mFont = QFont(parentPlot->font().family(), parentPlot->font().pointSize()*1.5, QFont::Bold);
13541 mFont = QFont(parentPlot->font().family(), parentPlot->font().pointSize()*1.5, QFont::Bold);
13550 mSelectedFont = QFont(parentPlot->font().family(), parentPlot->font().pointSize()*1.6, QFont::Bold);
13542 mSelectedFont = QFont(parentPlot->font().family(), parentPlot->font().pointSize()*1.6, QFont::Bold);
13551 }
13543 }
13552 setMargins(QMargins(5, 5, 5, 0));
13544 setMargins(QMargins(5, 5, 5, 0));
13553 }
13545 }
13554
13546
13555 /*! \overload
13547 /*! \overload
@@ -13557,17 +13549,17 QCPPlotTitle::QCPPlotTitle(QCustomPlot *
13557 Creates a new QCPPlotTitle instance and sets default values. The initial text is set to \a text.
13549 Creates a new QCPPlotTitle instance and sets default values. The initial text is set to \a text.
13558 */
13550 */
13559 QCPPlotTitle::QCPPlotTitle(QCustomPlot *parentPlot, const QString &text) :
13551 QCPPlotTitle::QCPPlotTitle(QCustomPlot *parentPlot, const QString &text) :
13560 QCPLayoutElement(parentPlot),
13552 QCPLayoutElement(parentPlot),
13561 mText(text),
13553 mText(text),
13562 mFont(QFont(parentPlot->font().family(), parentPlot->font().pointSize()*1.5, QFont::Bold)),
13554 mFont(QFont(parentPlot->font().family(), parentPlot->font().pointSize()*1.5, QFont::Bold)),
13563 mTextColor(Qt::black),
13555 mTextColor(Qt::black),
13564 mSelectedFont(QFont(parentPlot->font().family(), parentPlot->font().pointSize()*1.6, QFont::Bold)),
13556 mSelectedFont(QFont(parentPlot->font().family(), parentPlot->font().pointSize()*1.6, QFont::Bold)),
13565 mSelectedTextColor(Qt::blue),
13557 mSelectedTextColor(Qt::blue),
13566 mSelectable(false),
13558 mSelectable(false),
13567 mSelected(false)
13559 mSelected(false)
13568 {
13560 {
13569 setLayer(QLatin1String("axes"));
13561 setLayer(QLatin1String("axes"));
13570 setMargins(QMargins(5, 5, 5, 0));
13562 setMargins(QMargins(5, 5, 5, 0));
13571 }
13563 }
13572
13564
13573 /*!
13565 /*!
@@ -13577,7 +13569,7 QCPPlotTitle::QCPPlotTitle(QCustomPlot *
13577 */
13569 */
13578 void QCPPlotTitle::setText(const QString &text)
13570 void QCPPlotTitle::setText(const QString &text)
13579 {
13571 {
13580 mText = text;
13572 mText = text;
13581 }
13573 }
13582
13574
13583 /*!
13575 /*!
@@ -13587,7 +13579,7 void QCPPlotTitle::setText(const QString
13587 */
13579 */
13588 void QCPPlotTitle::setFont(const QFont &font)
13580 void QCPPlotTitle::setFont(const QFont &font)
13589 {
13581 {
13590 mFont = font;
13582 mFont = font;
13591 }
13583 }
13592
13584
13593 /*!
13585 /*!
@@ -13597,7 +13589,7 void QCPPlotTitle::setFont(const QFont &
13597 */
13589 */
13598 void QCPPlotTitle::setTextColor(const QColor &color)
13590 void QCPPlotTitle::setTextColor(const QColor &color)
13599 {
13591 {
13600 mTextColor = color;
13592 mTextColor = color;
13601 }
13593 }
13602
13594
13603 /*!
13595 /*!
@@ -13607,7 +13599,7 void QCPPlotTitle::setTextColor(const QC
13607 */
13599 */
13608 void QCPPlotTitle::setSelectedFont(const QFont &font)
13600 void QCPPlotTitle::setSelectedFont(const QFont &font)
13609 {
13601 {
13610 mSelectedFont = font;
13602 mSelectedFont = font;
13611 }
13603 }
13612
13604
13613 /*!
13605 /*!
@@ -13617,7 +13609,7 void QCPPlotTitle::setSelectedFont(const
13617 */
13609 */
13618 void QCPPlotTitle::setSelectedTextColor(const QColor &color)
13610 void QCPPlotTitle::setSelectedTextColor(const QColor &color)
13619 {
13611 {
13620 mSelectedTextColor = color;
13612 mSelectedTextColor = color;
13621 }
13613 }
13622
13614
13623 /*!
13615 /*!
@@ -13628,10 +13620,10 void QCPPlotTitle::setSelectedTextColor(
13628 */
13620 */
13629 void QCPPlotTitle::setSelectable(bool selectable)
13621 void QCPPlotTitle::setSelectable(bool selectable)
13630 {
13622 {
13631 if (mSelectable != selectable)
13623 if (mSelectable != selectable)
13632 {
13624 {
13633 mSelectable = selectable;
13625 mSelectable = selectable;
13634 emit selectableChanged(mSelectable);
13626 emit selectableChanged(mSelectable);
13635 }
13627 }
13636 }
13628 }
13637
13629
@@ -13644,84 +13636,84 void QCPPlotTitle::setSelectable(bool se
13644 */
13636 */
13645 void QCPPlotTitle::setSelected(bool selected)
13637 void QCPPlotTitle::setSelected(bool selected)
13646 {
13638 {
13647 if (mSelected != selected)
13639 if (mSelected != selected)
13648 {
13640 {
13649 mSelected = selected;
13641 mSelected = selected;
13650 emit selectionChanged(mSelected);
13642 emit selectionChanged(mSelected);
13651 }
13643 }
13652 }
13644 }
13653
13645
13654 /* inherits documentation from base class */
13646 /* inherits documentation from base class */
13655 void QCPPlotTitle::applyDefaultAntialiasingHint(QCPPainter *painter) const
13647 void QCPPlotTitle::applyDefaultAntialiasingHint(QCPPainter *painter) const
13656 {
13648 {
13657 applyAntialiasingHint(painter, mAntialiased, QCP::aeNone);
13649 applyAntialiasingHint(painter, mAntialiased, QCP::aeNone);
13658 }
13650 }
13659
13651
13660 /* inherits documentation from base class */
13652 /* inherits documentation from base class */
13661 void QCPPlotTitle::draw(QCPPainter *painter)
13653 void QCPPlotTitle::draw(QCPPainter *painter)
13662 {
13654 {
13663 painter->setFont(mainFont());
13655 painter->setFont(mainFont());
13664 painter->setPen(QPen(mainTextColor()));
13656 painter->setPen(QPen(mainTextColor()));
13665 painter->drawText(mRect, Qt::AlignCenter, mText, &mTextBoundingRect);
13657 painter->drawText(mRect, Qt::AlignCenter, mText, &mTextBoundingRect);
13666 }
13658 }
13667
13659
13668 /* inherits documentation from base class */
13660 /* inherits documentation from base class */
13669 QSize QCPPlotTitle::minimumSizeHint() const
13661 QSize QCPPlotTitle::minimumSizeHint() const
13670 {
13662 {
13671 QFontMetrics metrics(mFont);
13663 QFontMetrics metrics(mFont);
13672 QSize result = metrics.boundingRect(0, 0, 0, 0, Qt::AlignCenter, mText).size();
13664 QSize result = metrics.boundingRect(0, 0, 0, 0, Qt::AlignCenter, mText).size();
13673 result.rwidth() += mMargins.left() + mMargins.right();
13665 result.rwidth() += mMargins.left() + mMargins.right();
13674 result.rheight() += mMargins.top() + mMargins.bottom();
13666 result.rheight() += mMargins.top() + mMargins.bottom();
13675 return result;
13667 return result;
13676 }
13668 }
13677
13669
13678 /* inherits documentation from base class */
13670 /* inherits documentation from base class */
13679 QSize QCPPlotTitle::maximumSizeHint() const
13671 QSize QCPPlotTitle::maximumSizeHint() const
13680 {
13672 {
13681 QFontMetrics metrics(mFont);
13673 QFontMetrics metrics(mFont);
13682 QSize result = metrics.boundingRect(0, 0, 0, 0, Qt::AlignCenter, mText).size();
13674 QSize result = metrics.boundingRect(0, 0, 0, 0, Qt::AlignCenter, mText).size();
13683 result.rheight() += mMargins.top() + mMargins.bottom();
13675 result.rheight() += mMargins.top() + mMargins.bottom();
13684 result.setWidth(QWIDGETSIZE_MAX);
13676 result.setWidth(QWIDGETSIZE_MAX);
13685 return result;
13677 return result;
13686 }
13678 }
13687
13679
13688 /* inherits documentation from base class */
13680 /* inherits documentation from base class */
13689 void QCPPlotTitle::selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged)
13681 void QCPPlotTitle::selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged)
13690 {
13682 {
13691 Q_UNUSED(event)
13683 Q_UNUSED(event)
13692 Q_UNUSED(details)
13684 Q_UNUSED(details)
13693 if (mSelectable)
13685 if (mSelectable)
13694 {
13686 {
13695 bool selBefore = mSelected;
13687 bool selBefore = mSelected;
13696 setSelected(additive ? !mSelected : true);
13688 setSelected(additive ? !mSelected : true);
13697 if (selectionStateChanged)
13689 if (selectionStateChanged)
13698 *selectionStateChanged = mSelected != selBefore;
13690 *selectionStateChanged = mSelected != selBefore;
13699 }
13691 }
13700 }
13692 }
13701
13693
13702 /* inherits documentation from base class */
13694 /* inherits documentation from base class */
13703 void QCPPlotTitle::deselectEvent(bool *selectionStateChanged)
13695 void QCPPlotTitle::deselectEvent(bool *selectionStateChanged)
13704 {
13696 {
13705 if (mSelectable)
13697 if (mSelectable)
13706 {
13698 {
13707 bool selBefore = mSelected;
13699 bool selBefore = mSelected;
13708 setSelected(false);
13700 setSelected(false);
13709 if (selectionStateChanged)
13701 if (selectionStateChanged)
13710 *selectionStateChanged = mSelected != selBefore;
13702 *selectionStateChanged = mSelected != selBefore;
13711 }
13703 }
13712 }
13704 }
13713
13705
13714 /* inherits documentation from base class */
13706 /* inherits documentation from base class */
13715 double QCPPlotTitle::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
13707 double QCPPlotTitle::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
13716 {
13708 {
13717 Q_UNUSED(details)
13709 Q_UNUSED(details)
13718 if (onlySelectable && !mSelectable)
13710 if (onlySelectable && !mSelectable)
13719 return -1;
13711 return -1;
13720
13712
13721 if (mTextBoundingRect.contains(pos.toPoint()))
13713 if (mTextBoundingRect.contains(pos.toPoint()))
13722 return mParentPlot->selectionTolerance()*0.99;
13714 return mParentPlot->selectionTolerance()*0.99;
13723 else
13715 else
13724 return -1;
13716 return -1;
13725 }
13717 }
13726
13718
13727 /*! \internal
13719 /*! \internal
@@ -13731,7 +13723,7 double QCPPlotTitle::selectTest(const QP
13731 */
13723 */
13732 QFont QCPPlotTitle::mainFont() const
13724 QFont QCPPlotTitle::mainFont() const
13733 {
13725 {
13734 return mSelected ? mSelectedFont : mFont;
13726 return mSelected ? mSelectedFont : mFont;
13735 }
13727 }
13736
13728
13737 /*! \internal
13729 /*! \internal
@@ -13741,7 +13733,7 QFont QCPPlotTitle::mainFont() const
13741 */
13733 */
13742 QColor QCPPlotTitle::mainTextColor() const
13734 QColor QCPPlotTitle::mainTextColor() const
13743 {
13735 {
13744 return mSelected ? mSelectedTextColor : mTextColor;
13736 return mSelected ? mSelectedTextColor : mTextColor;
13745 }
13737 }
13746
13738
13747
13739
@@ -13842,60 +13834,60 QColor QCPPlotTitle::mainTextColor() con
13842 Constructs a new QCPColorScale.
13834 Constructs a new QCPColorScale.
13843 */
13835 */
13844 QCPColorScale::QCPColorScale(QCustomPlot *parentPlot) :
13836 QCPColorScale::QCPColorScale(QCustomPlot *parentPlot) :
13845 QCPLayoutElement(parentPlot),
13837 QCPLayoutElement(parentPlot),
13846 mType(QCPAxis::atTop), // set to atTop such that setType(QCPAxis::atRight) below doesn't skip work because it thinks it's already atRight
13838 mType(QCPAxis::atTop), // set to atTop such that setType(QCPAxis::atRight) below doesn't skip work because it thinks it's already atRight
13847 mDataScaleType(QCPAxis::stLinear),
13839 mDataScaleType(QCPAxis::stLinear),
13848 mBarWidth(20),
13840 mBarWidth(20),
13849 mAxisRect(new QCPColorScaleAxisRectPrivate(this))
13841 mAxisRect(new QCPColorScaleAxisRectPrivate(this))
13850 {
13842 {
13851 setMinimumMargins(QMargins(0, 6, 0, 6)); // for default right color scale types, keep some room at bottom and top (important if no margin group is used)
13843 setMinimumMargins(QMargins(0, 6, 0, 6)); // for default right color scale types, keep some room at bottom and top (important if no margin group is used)
13852 setType(QCPAxis::atRight);
13844 setType(QCPAxis::atRight);
13853 setDataRange(QCPRange(0, 6));
13845 setDataRange(QCPRange(0, 6));
13854 }
13846 }
13855
13847
13856 QCPColorScale::~QCPColorScale()
13848 QCPColorScale::~QCPColorScale()
13857 {
13849 {
13858 delete mAxisRect;
13850 delete mAxisRect;
13859 }
13851 }
13860
13852
13861 /* undocumented getter */
13853 /* undocumented getter */
13862 QString QCPColorScale::label() const
13854 QString QCPColorScale::label() const
13863 {
13855 {
13864 if (!mColorAxis)
13856 if (!mColorAxis)
13865 {
13857 {
13866 qDebug() << Q_FUNC_INFO << "internal color axis undefined";
13858 qDebug() << Q_FUNC_INFO << "internal color axis undefined";
13867 return QString();
13859 return QString();
13868 }
13860 }
13869
13861
13870 return mColorAxis.data()->label();
13862 return mColorAxis.data()->label();
13871 }
13863 }
13872
13864
13873 /* undocumented getter */
13865 /* undocumented getter */
13874 bool QCPColorScale::rangeDrag() const
13866 bool QCPColorScale::rangeDrag() const
13875 {
13867 {
13876 if (!mAxisRect)
13868 if (!mAxisRect)
13877 {
13869 {
13878 qDebug() << Q_FUNC_INFO << "internal axis rect was deleted";
13870 qDebug() << Q_FUNC_INFO << "internal axis rect was deleted";
13879 return false;
13871 return false;
13880 }
13872 }
13881
13873
13882 return mAxisRect.data()->rangeDrag().testFlag(QCPAxis::orientation(mType)) &&
13874 return mAxisRect.data()->rangeDrag().testFlag(QCPAxis::orientation(mType)) &&
13883 mAxisRect.data()->rangeDragAxis(QCPAxis::orientation(mType)) &&
13875 mAxisRect.data()->rangeDragAxis(QCPAxis::orientation(mType)) &&
13884 mAxisRect.data()->rangeDragAxis(QCPAxis::orientation(mType))->orientation() == QCPAxis::orientation(mType);
13876 mAxisRect.data()->rangeDragAxis(QCPAxis::orientation(mType))->orientation() == QCPAxis::orientation(mType);
13885 }
13877 }
13886
13878
13887 /* undocumented getter */
13879 /* undocumented getter */
13888 bool QCPColorScale::rangeZoom() const
13880 bool QCPColorScale::rangeZoom() const
13889 {
13881 {
13890 if (!mAxisRect)
13882 if (!mAxisRect)
13891 {
13883 {
13892 qDebug() << Q_FUNC_INFO << "internal axis rect was deleted";
13884 qDebug() << Q_FUNC_INFO << "internal axis rect was deleted";
13893 return false;
13885 return false;
13894 }
13886 }
13895
13887
13896 return mAxisRect.data()->rangeZoom().testFlag(QCPAxis::orientation(mType)) &&
13888 return mAxisRect.data()->rangeZoom().testFlag(QCPAxis::orientation(mType)) &&
13897 mAxisRect.data()->rangeZoomAxis(QCPAxis::orientation(mType)) &&
13889 mAxisRect.data()->rangeZoomAxis(QCPAxis::orientation(mType)) &&
13898 mAxisRect.data()->rangeZoomAxis(QCPAxis::orientation(mType))->orientation() == QCPAxis::orientation(mType);
13890 mAxisRect.data()->rangeZoomAxis(QCPAxis::orientation(mType))->orientation() == QCPAxis::orientation(mType);
13899 }
13891 }
13900
13892
13901 /*!
13893 /*!
@@ -13907,42 +13899,42 bool QCPColorScale::rangeZoom() const
13907 */
13899 */
13908 void QCPColorScale::setType(QCPAxis::AxisType type)
13900 void QCPColorScale::setType(QCPAxis::AxisType type)
13909 {
13901 {
13910 if (!mAxisRect)
13902 if (!mAxisRect)
13911 {
13903 {
13912 qDebug() << Q_FUNC_INFO << "internal axis rect was deleted";
13904 qDebug() << Q_FUNC_INFO << "internal axis rect was deleted";
13913 return;
13905 return;
13914 }
13906 }
13915 if (mType != type)
13907 if (mType != type)
13916 {
13908 {
13917 mType = type;
13909 mType = type;
13918 QCPRange rangeTransfer(0, 6);
13910 QCPRange rangeTransfer(0, 6);
13919 double logBaseTransfer = 10;
13911 double logBaseTransfer = 10;
13920 QString labelTransfer;
13912 QString labelTransfer;
13921 // revert some settings on old axis:
13913 // revert some settings on old axis:
13922 if (mColorAxis)
13914 if (mColorAxis)
13923 {
13915 {
13924 rangeTransfer = mColorAxis.data()->range();
13916 rangeTransfer = mColorAxis.data()->range();
13925 labelTransfer = mColorAxis.data()->label();
13917 labelTransfer = mColorAxis.data()->label();
13926 logBaseTransfer = mColorAxis.data()->scaleLogBase();
13918 logBaseTransfer = mColorAxis.data()->scaleLogBase();
13927 mColorAxis.data()->setLabel(QString());
13919 mColorAxis.data()->setLabel(QString());
13928 disconnect(mColorAxis.data(), SIGNAL(rangeChanged(QCPRange)), this, SLOT(setDataRange(QCPRange)));
13920 disconnect(mColorAxis.data(), SIGNAL(rangeChanged(QCPRange)), this, SLOT(setDataRange(QCPRange)));
13929 disconnect(mColorAxis.data(), SIGNAL(scaleTypeChanged(QCPAxis::ScaleType)), this, SLOT(setDataScaleType(QCPAxis::ScaleType)));
13921 disconnect(mColorAxis.data(), SIGNAL(scaleTypeChanged(QCPAxis::ScaleType)), this, SLOT(setDataScaleType(QCPAxis::ScaleType)));
13930 }
13922 }
13931 foreach (QCPAxis::AxisType atype, QList<QCPAxis::AxisType>() << QCPAxis::atLeft << QCPAxis::atRight << QCPAxis::atBottom << QCPAxis::atTop)
13923 foreach (QCPAxis::AxisType atype, QList<QCPAxis::AxisType>() << QCPAxis::atLeft << QCPAxis::atRight << QCPAxis::atBottom << QCPAxis::atTop)
13932 {
13924 {
13933 mAxisRect.data()->axis(atype)->setTicks(atype == mType);
13925 mAxisRect.data()->axis(atype)->setTicks(atype == mType);
13934 mAxisRect.data()->axis(atype)->setTickLabels(atype== mType);
13926 mAxisRect.data()->axis(atype)->setTickLabels(atype== mType);
13935 }
13927 }
13936 // set new mColorAxis pointer:
13928 // set new mColorAxis pointer:
13937 mColorAxis = mAxisRect.data()->axis(mType);
13929 mColorAxis = mAxisRect.data()->axis(mType);
13938 // transfer settings to new axis:
13930 // transfer settings to new axis:
13939 mColorAxis.data()->setRange(rangeTransfer); // transfer range of old axis to new one (necessary if axis changes from vertical to horizontal or vice versa)
13931 mColorAxis.data()->setRange(rangeTransfer); // transfer range of old axis to new one (necessary if axis changes from vertical to horizontal or vice versa)
13940 mColorAxis.data()->setLabel(labelTransfer);
13932 mColorAxis.data()->setLabel(labelTransfer);
13941 mColorAxis.data()->setScaleLogBase(logBaseTransfer); // scaleType is synchronized among axes in realtime via signals (connected in QCPColorScale ctor), so we only need to take care of log base here
13933 mColorAxis.data()->setScaleLogBase(logBaseTransfer); // scaleType is synchronized among axes in realtime via signals (connected in QCPColorScale ctor), so we only need to take care of log base here
13942 connect(mColorAxis.data(), SIGNAL(rangeChanged(QCPRange)), this, SLOT(setDataRange(QCPRange)));
13934 connect(mColorAxis.data(), SIGNAL(rangeChanged(QCPRange)), this, SLOT(setDataRange(QCPRange)));
13943 connect(mColorAxis.data(), SIGNAL(scaleTypeChanged(QCPAxis::ScaleType)), this, SLOT(setDataScaleType(QCPAxis::ScaleType)));
13935 connect(mColorAxis.data(), SIGNAL(scaleTypeChanged(QCPAxis::ScaleType)), this, SLOT(setDataScaleType(QCPAxis::ScaleType)));
13944 mAxisRect.data()->setRangeDragAxes(QCPAxis::orientation(mType) == Qt::Horizontal ? mColorAxis.data() : 0,
13936 mAxisRect.data()->setRangeDragAxes(QCPAxis::orientation(mType) == Qt::Horizontal ? mColorAxis.data() : 0,
13945 QCPAxis::orientation(mType) == Qt::Vertical ? mColorAxis.data() : 0);
13937 QCPAxis::orientation(mType) == Qt::Vertical ? mColorAxis.data() : 0);
13946 }
13938 }
13947 }
13939 }
13948
13940
@@ -13957,12 +13949,12 void QCPColorScale::setType(QCPAxis::Axi
13957 */
13949 */
13958 void QCPColorScale::setDataRange(const QCPRange &dataRange)
13950 void QCPColorScale::setDataRange(const QCPRange &dataRange)
13959 {
13951 {
13960 if (mDataRange.lower != dataRange.lower || mDataRange.upper != dataRange.upper)
13952 if (mDataRange.lower != dataRange.lower || mDataRange.upper != dataRange.upper)
13961 {
13953 {
13962 mDataRange = dataRange;
13954 mDataRange = dataRange;
13963 if (mColorAxis)
13955 if (mColorAxis)
13964 mColorAxis.data()->setRange(mDataRange);
13956 mColorAxis.data()->setRange(mDataRange);
13965 emit dataRangeChanged(mDataRange);
13957 emit dataRangeChanged(mDataRange);
13966 }
13958 }
13967 }
13959 }
13968
13960
@@ -13978,14 +13970,14 void QCPColorScale::setDataRange(const Q
13978 */
13970 */
13979 void QCPColorScale::setDataScaleType(QCPAxis::ScaleType scaleType)
13971 void QCPColorScale::setDataScaleType(QCPAxis::ScaleType scaleType)
13980 {
13972 {
13981 if (mDataScaleType != scaleType)
13973 if (mDataScaleType != scaleType)
13982 {
13974 {
13983 mDataScaleType = scaleType;
13975 mDataScaleType = scaleType;
13984 if (mColorAxis)
13976 if (mColorAxis)
13985 mColorAxis.data()->setScaleType(mDataScaleType);
13977 mColorAxis.data()->setScaleType(mDataScaleType);
13986 if (mDataScaleType == QCPAxis::stLogarithmic)
13978 if (mDataScaleType == QCPAxis::stLogarithmic)
13987 setDataRange(mDataRange.sanitizedForLogScale());
13979 setDataRange(mDataRange.sanitizedForLogScale());
13988 emit dataScaleTypeChanged(mDataScaleType);
13980 emit dataScaleTypeChanged(mDataScaleType);
13989 }
13981 }
13990 }
13982 }
13991
13983
@@ -13998,12 +13990,12 void QCPColorScale::setDataScaleType(QCP
13998 */
13990 */
13999 void QCPColorScale::setGradient(const QCPColorGradient &gradient)
13991 void QCPColorScale::setGradient(const QCPColorGradient &gradient)
14000 {
13992 {
14001 if (mGradient != gradient)
13993 if (mGradient != gradient)
14002 {
13994 {
14003 mGradient = gradient;
13995 mGradient = gradient;
14004 if (mAxisRect)
13996 if (mAxisRect)
14005 mAxisRect.data()->mGradientImageInvalidated = true;
13997 mAxisRect.data()->mGradientImageInvalidated = true;
14006 emit gradientChanged(mGradient);
13998 emit gradientChanged(mGradient);
14007 }
13999 }
14008 }
14000 }
14009
14001
@@ -14013,13 +14005,13 void QCPColorScale::setGradient(const QC
14013 */
14005 */
14014 void QCPColorScale::setLabel(const QString &str)
14006 void QCPColorScale::setLabel(const QString &str)
14015 {
14007 {
14016 if (!mColorAxis)
14008 if (!mColorAxis)
14017 {
14009 {
14018 qDebug() << Q_FUNC_INFO << "internal color axis undefined";
14010 qDebug() << Q_FUNC_INFO << "internal color axis undefined";
14019 return;
14011 return;
14020 }
14012 }
14021
14013
14022 mColorAxis.data()->setLabel(str);
14014 mColorAxis.data()->setLabel(str);
14023 }
14015 }
14024
14016
14025 /*!
14017 /*!
@@ -14028,7 +14020,7 void QCPColorScale::setLabel(const QStri
14028 */
14020 */
14029 void QCPColorScale::setBarWidth(int width)
14021 void QCPColorScale::setBarWidth(int width)
14030 {
14022 {
14031 mBarWidth = width;
14023 mBarWidth = width;
14032 }
14024 }
14033
14025
14034 /*!
14026 /*!
@@ -14039,16 +14031,16 void QCPColorScale::setBarWidth(int widt
14039 */
14031 */
14040 void QCPColorScale::setRangeDrag(bool enabled)
14032 void QCPColorScale::setRangeDrag(bool enabled)
14041 {
14033 {
14042 if (!mAxisRect)
14034 if (!mAxisRect)
14043 {
14035 {
14044 qDebug() << Q_FUNC_INFO << "internal axis rect was deleted";
14036 qDebug() << Q_FUNC_INFO << "internal axis rect was deleted";
14045 return;
14037 return;
14046 }
14038 }
14047
14039
14048 if (enabled)
14040 if (enabled)
14049 mAxisRect.data()->setRangeDrag(QCPAxis::orientation(mType));
14041 mAxisRect.data()->setRangeDrag(QCPAxis::orientation(mType));
14050 else
14042 else
14051 mAxisRect.data()->setRangeDrag(0);
14043 mAxisRect.data()->setRangeDrag(0);
14052 }
14044 }
14053
14045
14054 /*!
14046 /*!
@@ -14059,16 +14051,16 void QCPColorScale::setRangeDrag(bool en
14059 */
14051 */
14060 void QCPColorScale::setRangeZoom(bool enabled)
14052 void QCPColorScale::setRangeZoom(bool enabled)
14061 {
14053 {
14062 if (!mAxisRect)
14054 if (!mAxisRect)
14063 {
14055 {
14064 qDebug() << Q_FUNC_INFO << "internal axis rect was deleted";
14056 qDebug() << Q_FUNC_INFO << "internal axis rect was deleted";
14065 return;
14057 return;
14066 }
14058 }
14067
14059
14068 if (enabled)
14060 if (enabled)
14069 mAxisRect.data()->setRangeZoom(QCPAxis::orientation(mType));
14061 mAxisRect.data()->setRangeZoom(QCPAxis::orientation(mType));
14070 else
14062 else
14071 mAxisRect.data()->setRangeZoom(0);
14063 mAxisRect.data()->setRangeZoom(0);
14072 }
14064 }
14073
14065
14074 /*!
14066 /*!
@@ -14076,14 +14068,14 void QCPColorScale::setRangeZoom(bool en
14076 */
14068 */
14077 QList<QCPColorMap*> QCPColorScale::colorMaps() const
14069 QList<QCPColorMap*> QCPColorScale::colorMaps() const
14078 {
14070 {
14079 QList<QCPColorMap*> result;
14071 QList<QCPColorMap*> result;
14080 for (int i=0; i<mParentPlot->plottableCount(); ++i)
14072 for (int i=0; i<mParentPlot->plottableCount(); ++i)
14081 {
14073 {
14082 if (QCPColorMap *cm = qobject_cast<QCPColorMap*>(mParentPlot->plottable(i)))
14074 if (QCPColorMap *cm = qobject_cast<QCPColorMap*>(mParentPlot->plottable(i)))
14083 if (cm->colorScale() == this)
14075 if (cm->colorScale() == this)
14084 result.append(cm);
14076 result.append(cm);
14085 }
14077 }
14086 return result;
14078 return result;
14087 }
14079 }
14088
14080
14089 /*!
14081 /*!
@@ -14094,95 +14086,95 QList<QCPColorMap*> QCPColorScale::color
14094 */
14086 */
14095 void QCPColorScale::rescaleDataRange(bool onlyVisibleMaps)
14087 void QCPColorScale::rescaleDataRange(bool onlyVisibleMaps)
14096 {
14088 {
14097 QList<QCPColorMap*> maps = colorMaps();
14089 QList<QCPColorMap*> maps = colorMaps();
14098 QCPRange newRange;
14090 QCPRange newRange;
14099 bool haveRange = false;
14091 bool haveRange = false;
14100 int sign = 0; // TODO: should change this to QCPAbstractPlottable::SignDomain later (currently is protected, maybe move to QCP namespace)
14092 int sign = 0; // TODO: should change this to QCPAbstractPlottable::SignDomain later (currently is protected, maybe move to QCP namespace)
14101 if (mDataScaleType == QCPAxis::stLogarithmic)
14093 if (mDataScaleType == QCPAxis::stLogarithmic)
14102 sign = (mDataRange.upper < 0 ? -1 : 1);
14094 sign = (mDataRange.upper < 0 ? -1 : 1);
14103 for (int i=0; i<maps.size(); ++i)
14095 for (int i=0; i<maps.size(); ++i)
14104 {
14096 {
14105 if (!maps.at(i)->realVisibility() && onlyVisibleMaps)
14097 if (!maps.at(i)->realVisibility() && onlyVisibleMaps)
14106 continue;
14098 continue;
14107 QCPRange mapRange;
14099 QCPRange mapRange;
14108 if (maps.at(i)->colorScale() == this)
14100 if (maps.at(i)->colorScale() == this)
14109 {
14101 {
14110 bool currentFoundRange = true;
14102 bool currentFoundRange = true;
14111 mapRange = maps.at(i)->data()->dataBounds();
14103 mapRange = maps.at(i)->data()->dataBounds();
14112 if (sign == 1)
14104 if (sign == 1)
14113 {
14105 {
14114 if (mapRange.lower <= 0 && mapRange.upper > 0)
14106 if (mapRange.lower <= 0 && mapRange.upper > 0)
14115 mapRange.lower = mapRange.upper*1e-3;
14107 mapRange.lower = mapRange.upper*1e-3;
14116 else if (mapRange.lower <= 0 && mapRange.upper <= 0)
14108 else if (mapRange.lower <= 0 && mapRange.upper <= 0)
14117 currentFoundRange = false;
14109 currentFoundRange = false;
14118 } else if (sign == -1)
14110 } else if (sign == -1)
14119 {
14111 {
14120 if (mapRange.upper >= 0 && mapRange.lower < 0)
14112 if (mapRange.upper >= 0 && mapRange.lower < 0)
14121 mapRange.upper = mapRange.lower*1e-3;
14113 mapRange.upper = mapRange.lower*1e-3;
14122 else if (mapRange.upper >= 0 && mapRange.lower >= 0)
14114 else if (mapRange.upper >= 0 && mapRange.lower >= 0)
14123 currentFoundRange = false;
14115 currentFoundRange = false;
14124 }
14116 }
14125 if (currentFoundRange)
14117 if (currentFoundRange)
14126 {
14118 {
14127 if (!haveRange)
14119 if (!haveRange)
14128 newRange = mapRange;
14120 newRange = mapRange;
14129 else
14121 else
14130 newRange.expand(mapRange);
14122 newRange.expand(mapRange);
14131 haveRange = true;
14123 haveRange = true;
14132 }
14124 }
14133 }
14125 }
14134 }
14126 }
14135 if (haveRange)
14127 if (haveRange)
14136 {
14128 {
14137 if (!QCPRange::validRange(newRange)) // likely due to range being zero (plottable has only constant data in this dimension), shift current range to at least center the data
14129 if (!QCPRange::validRange(newRange)) // likely due to range being zero (plottable has only constant data in this dimension), shift current range to at least center the data
14138 {
14130 {
14139 double center = (newRange.lower+newRange.upper)*0.5; // upper and lower should be equal anyway, but just to make sure, incase validRange returned false for other reason
14131 double center = (newRange.lower+newRange.upper)*0.5; // upper and lower should be equal anyway, but just to make sure, incase validRange returned false for other reason
14140 if (mDataScaleType == QCPAxis::stLinear)
14132 if (mDataScaleType == QCPAxis::stLinear)
14141 {
14133 {
14142 newRange.lower = center-mDataRange.size()/2.0;
14134 newRange.lower = center-mDataRange.size()/2.0;
14143 newRange.upper = center+mDataRange.size()/2.0;
14135 newRange.upper = center+mDataRange.size()/2.0;
14144 } else // mScaleType == stLogarithmic
14136 } else // mScaleType == stLogarithmic
14145 {
14137 {
14146 newRange.lower = center/qSqrt(mDataRange.upper/mDataRange.lower);
14138 newRange.lower = center/qSqrt(mDataRange.upper/mDataRange.lower);
14147 newRange.upper = center*qSqrt(mDataRange.upper/mDataRange.lower);
14139 newRange.upper = center*qSqrt(mDataRange.upper/mDataRange.lower);
14148 }
14140 }
14149 }
14141 }
14150 setDataRange(newRange);
14142 setDataRange(newRange);
14151 }
14143 }
14152 }
14144 }
14153
14145
14154 /* inherits documentation from base class */
14146 /* inherits documentation from base class */
14155 void QCPColorScale::update(UpdatePhase phase)
14147 void QCPColorScale::update(UpdatePhase phase)
14156 {
14148 {
14157 QCPLayoutElement::update(phase);
14149 QCPLayoutElement::update(phase);
14158 if (!mAxisRect)
14150 if (!mAxisRect)
14159 {
14151 {
14160 qDebug() << Q_FUNC_INFO << "internal axis rect was deleted";
14152 qDebug() << Q_FUNC_INFO << "internal axis rect was deleted";
14161 return;
14153 return;
14162 }
14154 }
14163
14155
14164 mAxisRect.data()->update(phase);
14156 mAxisRect.data()->update(phase);
14165
14157
14166 switch (phase)
14158 switch (phase)
14167 {
14159 {
14168 case upMargins:
14160 case upMargins:
14169 {
14161 {
14170 if (mType == QCPAxis::atBottom || mType == QCPAxis::atTop)
14162 if (mType == QCPAxis::atBottom || mType == QCPAxis::atTop)
14171 {
14163 {
14172 setMaximumSize(QWIDGETSIZE_MAX, mBarWidth+mAxisRect.data()->margins().top()+mAxisRect.data()->margins().bottom()+margins().top()+margins().bottom());
14164 setMaximumSize(QWIDGETSIZE_MAX, mBarWidth+mAxisRect.data()->margins().top()+mAxisRect.data()->margins().bottom()+margins().top()+margins().bottom());
14173 setMinimumSize(0, mBarWidth+mAxisRect.data()->margins().top()+mAxisRect.data()->margins().bottom()+margins().top()+margins().bottom());
14165 setMinimumSize(0, mBarWidth+mAxisRect.data()->margins().top()+mAxisRect.data()->margins().bottom()+margins().top()+margins().bottom());
14174 } else
14166 } else
14175 {
14167 {
14176 setMaximumSize(mBarWidth+mAxisRect.data()->margins().left()+mAxisRect.data()->margins().right()+margins().left()+margins().right(), QWIDGETSIZE_MAX);
14168 setMaximumSize(mBarWidth+mAxisRect.data()->margins().left()+mAxisRect.data()->margins().right()+margins().left()+margins().right(), QWIDGETSIZE_MAX);
14177 setMinimumSize(mBarWidth+mAxisRect.data()->margins().left()+mAxisRect.data()->margins().right()+margins().left()+margins().right(), 0);
14169 setMinimumSize(mBarWidth+mAxisRect.data()->margins().left()+mAxisRect.data()->margins().right()+margins().left()+margins().right(), 0);
14178 }
14170 }
14179 break;
14171 break;
14180 }
14172 }
14181 case upLayout:
14173 case upLayout:
14182 {
14174 {
14183 mAxisRect.data()->setOuterRect(rect());
14175 mAxisRect.data()->setOuterRect(rect());
14184 break;
14176 break;
14185 }
14177 }
14186 default: break;
14178 default: break;
14187 }
14179 }
14188 }
14180 }
@@ -14190,51 +14182,51 void QCPColorScale::update(UpdatePhase p
14190 /* inherits documentation from base class */
14182 /* inherits documentation from base class */
14191 void QCPColorScale::applyDefaultAntialiasingHint(QCPPainter *painter) const
14183 void QCPColorScale::applyDefaultAntialiasingHint(QCPPainter *painter) const
14192 {
14184 {
14193 painter->setAntialiasing(false);
14185 painter->setAntialiasing(false);
14194 }
14186 }
14195
14187
14196 /* inherits documentation from base class */
14188 /* inherits documentation from base class */
14197 void QCPColorScale::mousePressEvent(QMouseEvent *event)
14189 void QCPColorScale::mousePressEvent(QMouseEvent *event)
14198 {
14190 {
14199 if (!mAxisRect)
14191 if (!mAxisRect)
14200 {
14192 {
14201 qDebug() << Q_FUNC_INFO << "internal axis rect was deleted";
14193 qDebug() << Q_FUNC_INFO << "internal axis rect was deleted";
14202 return;
14194 return;
14203 }
14195 }
14204 mAxisRect.data()->mousePressEvent(event);
14196 mAxisRect.data()->mousePressEvent(event);
14205 }
14197 }
14206
14198
14207 /* inherits documentation from base class */
14199 /* inherits documentation from base class */
14208 void QCPColorScale::mouseMoveEvent(QMouseEvent *event)
14200 void QCPColorScale::mouseMoveEvent(QMouseEvent *event)
14209 {
14201 {
14210 if (!mAxisRect)
14202 if (!mAxisRect)
14211 {
14203 {
14212 qDebug() << Q_FUNC_INFO << "internal axis rect was deleted";
14204 qDebug() << Q_FUNC_INFO << "internal axis rect was deleted";
14213 return;
14205 return;
14214 }
14206 }
14215 mAxisRect.data()->mouseMoveEvent(event);
14207 mAxisRect.data()->mouseMoveEvent(event);
14216 }
14208 }
14217
14209
14218 /* inherits documentation from base class */
14210 /* inherits documentation from base class */
14219 void QCPColorScale::mouseReleaseEvent(QMouseEvent *event)
14211 void QCPColorScale::mouseReleaseEvent(QMouseEvent *event)
14220 {
14212 {
14221 if (!mAxisRect)
14213 if (!mAxisRect)
14222 {
14214 {
14223 qDebug() << Q_FUNC_INFO << "internal axis rect was deleted";
14215 qDebug() << Q_FUNC_INFO << "internal axis rect was deleted";
14224 return;
14216 return;
14225 }
14217 }
14226 mAxisRect.data()->mouseReleaseEvent(event);
14218 mAxisRect.data()->mouseReleaseEvent(event);
14227 }
14219 }
14228
14220
14229 /* inherits documentation from base class */
14221 /* inherits documentation from base class */
14230 void QCPColorScale::wheelEvent(QWheelEvent *event)
14222 void QCPColorScale::wheelEvent(QWheelEvent *event)
14231 {
14223 {
14232 if (!mAxisRect)
14224 if (!mAxisRect)
14233 {
14225 {
14234 qDebug() << Q_FUNC_INFO << "internal axis rect was deleted";
14226 qDebug() << Q_FUNC_INFO << "internal axis rect was deleted";
14235 return;
14227 return;
14236 }
14228 }
14237 mAxisRect.data()->wheelEvent(event);
14229 mAxisRect.data()->wheelEvent(event);
14238 }
14230 }
14239
14231
14240 ////////////////////////////////////////////////////////////////////////////////////////////////////
14232 ////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -14256,35 +14248,35 void QCPColorScale::wheelEvent(QWheelEve
14256 Creates a new instance, as a child of \a parentColorScale.
14248 Creates a new instance, as a child of \a parentColorScale.
14257 */
14249 */
14258 QCPColorScaleAxisRectPrivate::QCPColorScaleAxisRectPrivate(QCPColorScale *parentColorScale) :
14250 QCPColorScaleAxisRectPrivate::QCPColorScaleAxisRectPrivate(QCPColorScale *parentColorScale) :
14259 QCPAxisRect(parentColorScale->parentPlot(), true),
14251 QCPAxisRect(parentColorScale->parentPlot(), true),
14260 mParentColorScale(parentColorScale),
14252 mParentColorScale(parentColorScale),
14261 mGradientImageInvalidated(true)
14253 mGradientImageInvalidated(true)
14262 {
14254 {
14263 setParentLayerable(parentColorScale);
14255 setParentLayerable(parentColorScale);
14264 setMinimumMargins(QMargins(0, 0, 0, 0));
14256 setMinimumMargins(QMargins(0, 0, 0, 0));
14265 foreach (QCPAxis::AxisType type, QList<QCPAxis::AxisType>() << QCPAxis::atBottom << QCPAxis::atTop << QCPAxis::atLeft << QCPAxis::atRight)
14257 foreach (QCPAxis::AxisType type, QList<QCPAxis::AxisType>() << QCPAxis::atBottom << QCPAxis::atTop << QCPAxis::atLeft << QCPAxis::atRight)
14266 {
14258 {
14267 axis(type)->setVisible(true);
14259 axis(type)->setVisible(true);
14268 axis(type)->grid()->setVisible(false);
14260 axis(type)->grid()->setVisible(false);
14269 axis(type)->setPadding(0);
14261 axis(type)->setPadding(0);
14270 connect(axis(type), SIGNAL(selectionChanged(QCPAxis::SelectableParts)), this, SLOT(axisSelectionChanged(QCPAxis::SelectableParts)));
14262 connect(axis(type), SIGNAL(selectionChanged(QCPAxis::SelectableParts)), this, SLOT(axisSelectionChanged(QCPAxis::SelectableParts)));
14271 connect(axis(type), SIGNAL(selectableChanged(QCPAxis::SelectableParts)), this, SLOT(axisSelectableChanged(QCPAxis::SelectableParts)));
14263 connect(axis(type), SIGNAL(selectableChanged(QCPAxis::SelectableParts)), this, SLOT(axisSelectableChanged(QCPAxis::SelectableParts)));
14272 }
14264 }
14273
14265
14274 connect(axis(QCPAxis::atLeft), SIGNAL(rangeChanged(QCPRange)), axis(QCPAxis::atRight), SLOT(setRange(QCPRange)));
14266 connect(axis(QCPAxis::atLeft), SIGNAL(rangeChanged(QCPRange)), axis(QCPAxis::atRight), SLOT(setRange(QCPRange)));
14275 connect(axis(QCPAxis::atRight), SIGNAL(rangeChanged(QCPRange)), axis(QCPAxis::atLeft), SLOT(setRange(QCPRange)));
14267 connect(axis(QCPAxis::atRight), SIGNAL(rangeChanged(QCPRange)), axis(QCPAxis::atLeft), SLOT(setRange(QCPRange)));
14276 connect(axis(QCPAxis::atBottom), SIGNAL(rangeChanged(QCPRange)), axis(QCPAxis::atTop), SLOT(setRange(QCPRange)));
14268 connect(axis(QCPAxis::atBottom), SIGNAL(rangeChanged(QCPRange)), axis(QCPAxis::atTop), SLOT(setRange(QCPRange)));
14277 connect(axis(QCPAxis::atTop), SIGNAL(rangeChanged(QCPRange)), axis(QCPAxis::atBottom), SLOT(setRange(QCPRange)));
14269 connect(axis(QCPAxis::atTop), SIGNAL(rangeChanged(QCPRange)), axis(QCPAxis::atBottom), SLOT(setRange(QCPRange)));
14278 connect(axis(QCPAxis::atLeft), SIGNAL(scaleTypeChanged(QCPAxis::ScaleType)), axis(QCPAxis::atRight), SLOT(setScaleType(QCPAxis::ScaleType)));
14270 connect(axis(QCPAxis::atLeft), SIGNAL(scaleTypeChanged(QCPAxis::ScaleType)), axis(QCPAxis::atRight), SLOT(setScaleType(QCPAxis::ScaleType)));
14279 connect(axis(QCPAxis::atRight), SIGNAL(scaleTypeChanged(QCPAxis::ScaleType)), axis(QCPAxis::atLeft), SLOT(setScaleType(QCPAxis::ScaleType)));
14271 connect(axis(QCPAxis::atRight), SIGNAL(scaleTypeChanged(QCPAxis::ScaleType)), axis(QCPAxis::atLeft), SLOT(setScaleType(QCPAxis::ScaleType)));
14280 connect(axis(QCPAxis::atBottom), SIGNAL(scaleTypeChanged(QCPAxis::ScaleType)), axis(QCPAxis::atTop), SLOT(setScaleType(QCPAxis::ScaleType)));
14272 connect(axis(QCPAxis::atBottom), SIGNAL(scaleTypeChanged(QCPAxis::ScaleType)), axis(QCPAxis::atTop), SLOT(setScaleType(QCPAxis::ScaleType)));
14281 connect(axis(QCPAxis::atTop), SIGNAL(scaleTypeChanged(QCPAxis::ScaleType)), axis(QCPAxis::atBottom), SLOT(setScaleType(QCPAxis::ScaleType)));
14273 connect(axis(QCPAxis::atTop), SIGNAL(scaleTypeChanged(QCPAxis::ScaleType)), axis(QCPAxis::atBottom), SLOT(setScaleType(QCPAxis::ScaleType)));
14282
14274
14283 // make layer transfers of color scale transfer to axis rect and axes
14275 // make layer transfers of color scale transfer to axis rect and axes
14284 // the axes must be set after axis rect, such that they appear above color gradient drawn by axis rect:
14276 // the axes must be set after axis rect, such that they appear above color gradient drawn by axis rect:
14285 connect(parentColorScale, SIGNAL(layerChanged(QCPLayer*)), this, SLOT(setLayer(QCPLayer*)));
14277 connect(parentColorScale, SIGNAL(layerChanged(QCPLayer*)), this, SLOT(setLayer(QCPLayer*)));
14286 foreach (QCPAxis::AxisType type, QList<QCPAxis::AxisType>() << QCPAxis::atBottom << QCPAxis::atTop << QCPAxis::atLeft << QCPAxis::atRight)
14278 foreach (QCPAxis::AxisType type, QList<QCPAxis::AxisType>() << QCPAxis::atBottom << QCPAxis::atTop << QCPAxis::atLeft << QCPAxis::atRight)
14287 connect(parentColorScale, SIGNAL(layerChanged(QCPLayer*)), axis(type), SLOT(setLayer(QCPLayer*)));
14279 connect(parentColorScale, SIGNAL(layerChanged(QCPLayer*)), axis(type), SLOT(setLayer(QCPLayer*)));
14288 }
14280 }
14289
14281
14290 /*! \internal
14282 /*! \internal
@@ -14293,19 +14285,19 QCPColorScaleAxisRectPrivate::QCPColorSc
14293 */
14285 */
14294 void QCPColorScaleAxisRectPrivate::draw(QCPPainter *painter)
14286 void QCPColorScaleAxisRectPrivate::draw(QCPPainter *painter)
14295 {
14287 {
14296 if (mGradientImageInvalidated)
14288 if (mGradientImageInvalidated)
14297 updateGradientImage();
14289 updateGradientImage();
14298
14290
14299 bool mirrorHorz = false;
14291 bool mirrorHorz = false;
14300 bool mirrorVert = false;
14292 bool mirrorVert = false;
14301 if (mParentColorScale->mColorAxis)
14293 if (mParentColorScale->mColorAxis)
14302 {
14294 {
14303 mirrorHorz = mParentColorScale->mColorAxis.data()->rangeReversed() && (mParentColorScale->type() == QCPAxis::atBottom || mParentColorScale->type() == QCPAxis::atTop);
14295 mirrorHorz = mParentColorScale->mColorAxis.data()->rangeReversed() && (mParentColorScale->type() == QCPAxis::atBottom || mParentColorScale->type() == QCPAxis::atTop);
14304 mirrorVert = mParentColorScale->mColorAxis.data()->rangeReversed() && (mParentColorScale->type() == QCPAxis::atLeft || mParentColorScale->type() == QCPAxis::atRight);
14296 mirrorVert = mParentColorScale->mColorAxis.data()->rangeReversed() && (mParentColorScale->type() == QCPAxis::atLeft || mParentColorScale->type() == QCPAxis::atRight);
14305 }
14297 }
14306
14298
14307 painter->drawImage(rect(), mGradientImage.mirrored(mirrorHorz, mirrorVert));
14299 painter->drawImage(rect(), mGradientImage.mirrored(mirrorHorz, mirrorVert));
14308 QCPAxisRect::draw(painter);
14300 QCPAxisRect::draw(painter);
14309 }
14301 }
14310
14302
14311 /*! \internal
14303 /*! \internal
@@ -14315,39 +14307,39 void QCPColorScaleAxisRectPrivate::draw(
14315 */
14307 */
14316 void QCPColorScaleAxisRectPrivate::updateGradientImage()
14308 void QCPColorScaleAxisRectPrivate::updateGradientImage()
14317 {
14309 {
14318 if (rect().isEmpty())
14310 if (rect().isEmpty())
14319 return;
14311 return;
14320
14312
14321 int n = mParentColorScale->mGradient.levelCount();
14313 int n = mParentColorScale->mGradient.levelCount();
14322 int w, h;
14314 int w, h;
14323 QVector<double> data(n);
14315 QVector<double> data(n);
14324 for (int i=0; i<n; ++i)
14316 for (int i=0; i<n; ++i)
14325 data[i] = i;
14317 data[i] = i;
14326 if (mParentColorScale->mType == QCPAxis::atBottom || mParentColorScale->mType == QCPAxis::atTop)
14318 if (mParentColorScale->mType == QCPAxis::atBottom || mParentColorScale->mType == QCPAxis::atTop)
14327 {
14319 {
14328 w = n;
14320 w = n;
14329 h = rect().height();
14321 h = rect().height();
14330 mGradientImage = QImage(w, h, QImage::Format_RGB32);
14322 mGradientImage = QImage(w, h, QImage::Format_RGB32);
14331 QVector<QRgb*> pixels;
14323 QVector<QRgb*> pixels;
14332 for (int y=0; y<h; ++y)
14324 for (int y=0; y<h; ++y)
14333 pixels.append(reinterpret_cast<QRgb*>(mGradientImage.scanLine(y)));
14325 pixels.append(reinterpret_cast<QRgb*>(mGradientImage.scanLine(y)));
14334 mParentColorScale->mGradient.colorize(data.constData(), QCPRange(0, n-1), pixels.first(), n);
14326 mParentColorScale->mGradient.colorize(data.constData(), QCPRange(0, n-1), pixels.first(), n);
14335 for (int y=1; y<h; ++y)
14327 for (int y=1; y<h; ++y)
14336 memcpy(pixels.at(y), pixels.first(), n*sizeof(QRgb));
14328 memcpy(pixels.at(y), pixels.first(), n*sizeof(QRgb));
14337 } else
14329 } else
14338 {
14330 {
14339 w = rect().width();
14331 w = rect().width();
14340 h = n;
14332 h = n;
14341 mGradientImage = QImage(w, h, QImage::Format_RGB32);
14333 mGradientImage = QImage(w, h, QImage::Format_RGB32);
14342 for (int y=0; y<h; ++y)
14334 for (int y=0; y<h; ++y)
14343 {
14335 {
14344 QRgb *pixels = reinterpret_cast<QRgb*>(mGradientImage.scanLine(y));
14336 QRgb *pixels = reinterpret_cast<QRgb*>(mGradientImage.scanLine(y));
14345 const QRgb lineColor = mParentColorScale->mGradient.color(data[h-1-y], QCPRange(0, n-1));
14337 const QRgb lineColor = mParentColorScale->mGradient.color(data[h-1-y], QCPRange(0, n-1));
14346 for (int x=0; x<w; ++x)
14338 for (int x=0; x<w; ++x)
14347 pixels[x] = lineColor;
14339 pixels[x] = lineColor;
14348 }
14340 }
14349 }
14341 }
14350 mGradientImageInvalidated = false;
14342 mGradientImageInvalidated = false;
14351 }
14343 }
14352
14344
14353 /*! \internal
14345 /*! \internal
@@ -14357,19 +14349,19 void QCPColorScaleAxisRectPrivate::updat
14357 */
14349 */
14358 void QCPColorScaleAxisRectPrivate::axisSelectionChanged(QCPAxis::SelectableParts selectedParts)
14350 void QCPColorScaleAxisRectPrivate::axisSelectionChanged(QCPAxis::SelectableParts selectedParts)
14359 {
14351 {
14360 // axis bases of four axes shall always (de-)selected synchronously:
14352 // axis bases of four axes shall always (de-)selected synchronously:
14361 foreach (QCPAxis::AxisType type, QList<QCPAxis::AxisType>() << QCPAxis::atBottom << QCPAxis::atTop << QCPAxis::atLeft << QCPAxis::atRight)
14353 foreach (QCPAxis::AxisType type, QList<QCPAxis::AxisType>() << QCPAxis::atBottom << QCPAxis::atTop << QCPAxis::atLeft << QCPAxis::atRight)
14362 {
14354 {
14363 if (QCPAxis *senderAxis = qobject_cast<QCPAxis*>(sender()))
14355 if (QCPAxis *senderAxis = qobject_cast<QCPAxis*>(sender()))
14364 if (senderAxis->axisType() == type)
14356 if (senderAxis->axisType() == type)
14365 continue;
14357 continue;
14366
14358
14367 if (axis(type)->selectableParts().testFlag(QCPAxis::spAxis))
14359 if (axis(type)->selectableParts().testFlag(QCPAxis::spAxis))
14368 {
14360 {
14369 if (selectedParts.testFlag(QCPAxis::spAxis))
14361 if (selectedParts.testFlag(QCPAxis::spAxis))
14370 axis(type)->setSelectedParts(axis(type)->selectedParts() | QCPAxis::spAxis);
14362 axis(type)->setSelectedParts(axis(type)->selectedParts() | QCPAxis::spAxis);
14371 else
14363 else
14372 axis(type)->setSelectedParts(axis(type)->selectedParts() & ~QCPAxis::spAxis);
14364 axis(type)->setSelectedParts(axis(type)->selectedParts() & ~QCPAxis::spAxis);
14373 }
14365 }
14374 }
14366 }
14375 }
14367 }
@@ -14381,19 +14373,19 void QCPColorScaleAxisRectPrivate::axisS
14381 */
14373 */
14382 void QCPColorScaleAxisRectPrivate::axisSelectableChanged(QCPAxis::SelectableParts selectableParts)
14374 void QCPColorScaleAxisRectPrivate::axisSelectableChanged(QCPAxis::SelectableParts selectableParts)
14383 {
14375 {
14384 // synchronize axis base selectability:
14376 // synchronize axis base selectability:
14385 foreach (QCPAxis::AxisType type, QList<QCPAxis::AxisType>() << QCPAxis::atBottom << QCPAxis::atTop << QCPAxis::atLeft << QCPAxis::atRight)
14377 foreach (QCPAxis::AxisType type, QList<QCPAxis::AxisType>() << QCPAxis::atBottom << QCPAxis::atTop << QCPAxis::atLeft << QCPAxis::atRight)
14386 {
14378 {
14387 if (QCPAxis *senderAxis = qobject_cast<QCPAxis*>(sender()))
14379 if (QCPAxis *senderAxis = qobject_cast<QCPAxis*>(sender()))
14388 if (senderAxis->axisType() == type)
14380 if (senderAxis->axisType() == type)
14389 continue;
14381 continue;
14390
14382
14391 if (axis(type)->selectableParts().testFlag(QCPAxis::spAxis))
14383 if (axis(type)->selectableParts().testFlag(QCPAxis::spAxis))
14392 {
14384 {
14393 if (selectableParts.testFlag(QCPAxis::spAxis))
14385 if (selectableParts.testFlag(QCPAxis::spAxis))
14394 axis(type)->setSelectableParts(axis(type)->selectableParts() | QCPAxis::spAxis);
14386 axis(type)->setSelectableParts(axis(type)->selectableParts() | QCPAxis::spAxis);
14395 else
14387 else
14396 axis(type)->setSelectableParts(axis(type)->selectableParts() & ~QCPAxis::spAxis);
14388 axis(type)->setSelectableParts(axis(type)->selectableParts() & ~QCPAxis::spAxis);
14397 }
14389 }
14398 }
14390 }
14399 }
14391 }
@@ -14423,12 +14415,12 void QCPColorScaleAxisRectPrivate::axisS
14423 Constructs a data point with key, value and all errors set to zero.
14415 Constructs a data point with key, value and all errors set to zero.
14424 */
14416 */
14425 QCPData::QCPData() :
14417 QCPData::QCPData() :
14426 key(0),
14418 key(0),
14427 value(0),
14419 value(0),
14428 keyErrorPlus(0),
14420 keyErrorPlus(0),
14429 keyErrorMinus(0),
14421 keyErrorMinus(0),
14430 valueErrorPlus(0),
14422 valueErrorPlus(0),
14431 valueErrorMinus(0)
14423 valueErrorMinus(0)
14432 {
14424 {
14433 }
14425 }
14434
14426
@@ -14436,12 +14428,12 QCPData::QCPData() :
14436 Constructs a data point with the specified \a key and \a value. All errors are set to zero.
14428 Constructs a data point with the specified \a key and \a value. All errors are set to zero.
14437 */
14429 */
14438 QCPData::QCPData(double key, double value) :
14430 QCPData::QCPData(double key, double value) :
14439 key(key),
14431 key(key),
14440 value(value),
14432 value(value),
14441 keyErrorPlus(0),
14433 keyErrorPlus(0),
14442 keyErrorMinus(0),
14434 keyErrorMinus(0),
14443 valueErrorPlus(0),
14435 valueErrorPlus(0),
14444 valueErrorMinus(0)
14436 valueErrorMinus(0)
14445 {
14437 {
14446 }
14438 }
14447
14439
@@ -14507,29 +14499,27 QCPData::QCPData(double key, double valu
14507 To directly create a graph inside a plot, you can also use the simpler QCustomPlot::addGraph function.
14499 To directly create a graph inside a plot, you can also use the simpler QCustomPlot::addGraph function.
14508 */
14500 */
14509 QCPGraph::QCPGraph(QCPAxis *keyAxis, QCPAxis *valueAxis) :
14501 QCPGraph::QCPGraph(QCPAxis *keyAxis, QCPAxis *valueAxis) :
14510 QCPAbstractPlottable(keyAxis, valueAxis)
14502 QCPAbstractPlottable(keyAxis, valueAxis)
14511 {
14503 {
14512 mData = new QCPDataMap;
14504 mData = new QCPDataMap;
14513 mDataVector = new QVector<QCPData>();
14505
14514 setPen(QPen(Qt::blue, 0));
14506 setPen(QPen(Qt::blue, 0));
14515 setErrorPen(QPen(Qt::black));
14507 setErrorPen(QPen(Qt::black));
14516 setBrush(Qt::NoBrush);
14508 setBrush(Qt::NoBrush);
14517 setSelectedPen(QPen(QColor(80, 80, 255), 2.5));
14509 setSelectedPen(QPen(QColor(80, 80, 255), 2.5));
14518 setSelectedBrush(Qt::NoBrush);
14510 setSelectedBrush(Qt::NoBrush);
14519
14511
14520 setLineStyle(lsLine);
14512 setLineStyle(lsLine);
14521 setErrorType(etNone);
14513 setErrorType(etNone);
14522 setErrorBarSize(6);
14514 setErrorBarSize(6);
14523 setErrorBarSkipSymbol(true);
14515 setErrorBarSkipSymbol(true);
14524 setChannelFillGraph(0);
14516 setChannelFillGraph(0);
14525 setAdaptiveSampling(true);
14517 setAdaptiveSampling(true);
14526 setUseFastVectors(false);
14527 }
14518 }
14528
14519
14529 QCPGraph::~QCPGraph()
14520 QCPGraph::~QCPGraph()
14530 {
14521 {
14531 delete mData;
14522 delete mData;
14532 delete mDataVector;
14533 }
14523 }
14534
14524
14535 /*!
14525 /*!
@@ -14544,18 +14534,18 QCPGraph::~QCPGraph()
14544 */
14534 */
14545 void QCPGraph::setData(QCPDataMap *data, bool copy)
14535 void QCPGraph::setData(QCPDataMap *data, bool copy)
14546 {
14536 {
14547 if (mData == data)
14537 if (mData == data)
14548 {
14538 {
14549 qDebug() << Q_FUNC_INFO << "The data pointer is already in (and owned by) this plottable" << reinterpret_cast<quintptr>(data);
14539 qDebug() << Q_FUNC_INFO << "The data pointer is already in (and owned by) this plottable" << reinterpret_cast<quintptr>(data);
14550 return;
14540 return;
14551 }
14541 }
14552 if (copy)
14542 if (copy)
14553 {
14543 {
14554 *mData = *data;
14544 *mData = *data;
14555 } else
14545 } else
14556 {
14546 {
14557 delete mData;
14547 delete mData;
14558 mData = data;
14548 mData = data;
14559 }
14549 }
14560 }
14550 }
14561
14551
@@ -14567,24 +14557,15 void QCPGraph::setData(QCPDataMap *data,
14567 */
14557 */
14568 void QCPGraph::setData(const QVector<double> &key, const QVector<double> &value)
14558 void QCPGraph::setData(const QVector<double> &key, const QVector<double> &value)
14569 {
14559 {
14570 mData->clear();
14560 mData->clear();
14571 int n = key.size();
14561 int n = key.size();
14572 n = qMin(n, value.size());
14562 n = qMin(n, value.size());
14573 QCPData newData;
14563 QCPData newData;
14574 for (int i=0; i<n; ++i)
14564 for (int i=0; i<n; ++i)
14575 {
14565 {
14576 newData.key = key[i];
14566 newData.key = key[i];
14577 newData.value = value[i];
14567 newData.value = value[i];
14578 mData->insertMulti(newData.key, newData);
14568 mData->insertMulti(newData.key, newData);
14579 }
14580 }
14581
14582 void QCPGraph::setData(QVector<QCPData> *data)
14583 {
14584 if(data!=mDataVector)
14585 {
14586 delete this->mDataVector;
14587 this->mDataVector = data;
14588 }
14569 }
14589 }
14570 }
14590
14571
@@ -14599,18 +14580,18 void QCPGraph::setData(QVector<QCPData>
14599 */
14580 */
14600 void QCPGraph::setDataValueError(const QVector<double> &key, const QVector<double> &value, const QVector<double> &valueError)
14581 void QCPGraph::setDataValueError(const QVector<double> &key, const QVector<double> &value, const QVector<double> &valueError)
14601 {
14582 {
14602 mData->clear();
14583 mData->clear();
14603 int n = key.size();
14584 int n = key.size();
14604 n = qMin(n, value.size());
14585 n = qMin(n, value.size());
14605 n = qMin(n, valueError.size());
14586 n = qMin(n, valueError.size());
14606 QCPData newData;
14587 QCPData newData;
14607 for (int i=0; i<n; ++i)
14588 for (int i=0; i<n; ++i)
14608 {
14589 {
14609 newData.key = key[i];
14590 newData.key = key[i];
14610 newData.value = value[i];
14591 newData.value = value[i];
14611 newData.valueErrorMinus = valueError[i];
14592 newData.valueErrorMinus = valueError[i];
14612 newData.valueErrorPlus = valueError[i];
14593 newData.valueErrorPlus = valueError[i];
14613 mData->insertMulti(key[i], newData);
14594 mData->insertMulti(key[i], newData);
14614 }
14595 }
14615 }
14596 }
14616
14597
@@ -14625,19 +14606,19 void QCPGraph::setDataValueError(const Q
14625 */
14606 */
14626 void QCPGraph::setDataValueError(const QVector<double> &key, const QVector<double> &value, const QVector<double> &valueErrorMinus, const QVector<double> &valueErrorPlus)
14607 void QCPGraph::setDataValueError(const QVector<double> &key, const QVector<double> &value, const QVector<double> &valueErrorMinus, const QVector<double> &valueErrorPlus)
14627 {
14608 {
14628 mData->clear();
14609 mData->clear();
14629 int n = key.size();
14610 int n = key.size();
14630 n = qMin(n, value.size());
14611 n = qMin(n, value.size());
14631 n = qMin(n, valueErrorMinus.size());
14612 n = qMin(n, valueErrorMinus.size());
14632 n = qMin(n, valueErrorPlus.size());
14613 n = qMin(n, valueErrorPlus.size());
14633 QCPData newData;
14614 QCPData newData;
14634 for (int i=0; i<n; ++i)
14615 for (int i=0; i<n; ++i)
14635 {
14616 {
14636 newData.key = key[i];
14617 newData.key = key[i];
14637 newData.value = value[i];
14618 newData.value = value[i];
14638 newData.valueErrorMinus = valueErrorMinus[i];
14619 newData.valueErrorMinus = valueErrorMinus[i];
14639 newData.valueErrorPlus = valueErrorPlus[i];
14620 newData.valueErrorPlus = valueErrorPlus[i];
14640 mData->insertMulti(key[i], newData);
14621 mData->insertMulti(key[i], newData);
14641 }
14622 }
14642 }
14623 }
14643
14624
@@ -14652,18 +14633,18 void QCPGraph::setDataValueError(const Q
14652 */
14633 */
14653 void QCPGraph::setDataKeyError(const QVector<double> &key, const QVector<double> &value, const QVector<double> &keyError)
14634 void QCPGraph::setDataKeyError(const QVector<double> &key, const QVector<double> &value, const QVector<double> &keyError)
14654 {
14635 {
14655 mData->clear();
14636 mData->clear();
14656 int n = key.size();
14637 int n = key.size();
14657 n = qMin(n, value.size());
14638 n = qMin(n, value.size());
14658 n = qMin(n, keyError.size());
14639 n = qMin(n, keyError.size());
14659 QCPData newData;
14640 QCPData newData;
14660 for (int i=0; i<n; ++i)
14641 for (int i=0; i<n; ++i)
14661 {
14642 {
14662 newData.key = key[i];
14643 newData.key = key[i];
14663 newData.value = value[i];
14644 newData.value = value[i];
14664 newData.keyErrorMinus = keyError[i];
14645 newData.keyErrorMinus = keyError[i];
14665 newData.keyErrorPlus = keyError[i];
14646 newData.keyErrorPlus = keyError[i];
14666 mData->insertMulti(key[i], newData);
14647 mData->insertMulti(key[i], newData);
14667 }
14648 }
14668 }
14649 }
14669
14650
@@ -14678,19 +14659,19 void QCPGraph::setDataKeyError(const QVe
14678 */
14659 */
14679 void QCPGraph::setDataKeyError(const QVector<double> &key, const QVector<double> &value, const QVector<double> &keyErrorMinus, const QVector<double> &keyErrorPlus)
14660 void QCPGraph::setDataKeyError(const QVector<double> &key, const QVector<double> &value, const QVector<double> &keyErrorMinus, const QVector<double> &keyErrorPlus)
14680 {
14661 {
14681 mData->clear();
14662 mData->clear();
14682 int n = key.size();
14663 int n = key.size();
14683 n = qMin(n, value.size());
14664 n = qMin(n, value.size());
14684 n = qMin(n, keyErrorMinus.size());
14665 n = qMin(n, keyErrorMinus.size());
14685 n = qMin(n, keyErrorPlus.size());
14666 n = qMin(n, keyErrorPlus.size());
14686 QCPData newData;
14667 QCPData newData;
14687 for (int i=0; i<n; ++i)
14668 for (int i=0; i<n; ++i)
14688 {
14669 {
14689 newData.key = key[i];
14670 newData.key = key[i];
14690 newData.value = value[i];
14671 newData.value = value[i];
14691 newData.keyErrorMinus = keyErrorMinus[i];
14672 newData.keyErrorMinus = keyErrorMinus[i];
14692 newData.keyErrorPlus = keyErrorPlus[i];
14673 newData.keyErrorPlus = keyErrorPlus[i];
14693 mData->insertMulti(key[i], newData);
14674 mData->insertMulti(key[i], newData);
14694 }
14675 }
14695 }
14676 }
14696
14677
@@ -14705,21 +14686,21 void QCPGraph::setDataKeyError(const QVe
14705 */
14686 */
14706 void QCPGraph::setDataBothError(const QVector<double> &key, const QVector<double> &value, const QVector<double> &keyError, const QVector<double> &valueError)
14687 void QCPGraph::setDataBothError(const QVector<double> &key, const QVector<double> &value, const QVector<double> &keyError, const QVector<double> &valueError)
14707 {
14688 {
14708 mData->clear();
14689 mData->clear();
14709 int n = key.size();
14690 int n = key.size();
14710 n = qMin(n, value.size());
14691 n = qMin(n, value.size());
14711 n = qMin(n, valueError.size());
14692 n = qMin(n, valueError.size());
14712 n = qMin(n, keyError.size());
14693 n = qMin(n, keyError.size());
14713 QCPData newData;
14694 QCPData newData;
14714 for (int i=0; i<n; ++i)
14695 for (int i=0; i<n; ++i)
14715 {
14696 {
14716 newData.key = key[i];
14697 newData.key = key[i];
14717 newData.value = value[i];
14698 newData.value = value[i];
14718 newData.keyErrorMinus = keyError[i];
14699 newData.keyErrorMinus = keyError[i];
14719 newData.keyErrorPlus = keyError[i];
14700 newData.keyErrorPlus = keyError[i];
14720 newData.valueErrorMinus = valueError[i];
14701 newData.valueErrorMinus = valueError[i];
14721 newData.valueErrorPlus = valueError[i];
14702 newData.valueErrorPlus = valueError[i];
14722 mData->insertMulti(key[i], newData);
14703 mData->insertMulti(key[i], newData);
14723 }
14704 }
14724 }
14705 }
14725
14706
@@ -14734,23 +14715,23 void QCPGraph::setDataBothError(const QV
14734 */
14715 */
14735 void QCPGraph::setDataBothError(const QVector<double> &key, const QVector<double> &value, const QVector<double> &keyErrorMinus, const QVector<double> &keyErrorPlus, const QVector<double> &valueErrorMinus, const QVector<double> &valueErrorPlus)
14716 void QCPGraph::setDataBothError(const QVector<double> &key, const QVector<double> &value, const QVector<double> &keyErrorMinus, const QVector<double> &keyErrorPlus, const QVector<double> &valueErrorMinus, const QVector<double> &valueErrorPlus)
14736 {
14717 {
14737 mData->clear();
14718 mData->clear();
14738 int n = key.size();
14719 int n = key.size();
14739 n = qMin(n, value.size());
14720 n = qMin(n, value.size());
14740 n = qMin(n, valueErrorMinus.size());
14721 n = qMin(n, valueErrorMinus.size());
14741 n = qMin(n, valueErrorPlus.size());
14722 n = qMin(n, valueErrorPlus.size());
14742 n = qMin(n, keyErrorMinus.size());
14723 n = qMin(n, keyErrorMinus.size());
14743 n = qMin(n, keyErrorPlus.size());
14724 n = qMin(n, keyErrorPlus.size());
14744 QCPData newData;
14725 QCPData newData;
14745 for (int i=0; i<n; ++i)
14726 for (int i=0; i<n; ++i)
14746 {
14727 {
14747 newData.key = key[i];
14728 newData.key = key[i];
14748 newData.value = value[i];
14729 newData.value = value[i];
14749 newData.keyErrorMinus = keyErrorMinus[i];
14730 newData.keyErrorMinus = keyErrorMinus[i];
14750 newData.keyErrorPlus = keyErrorPlus[i];
14731 newData.keyErrorPlus = keyErrorPlus[i];
14751 newData.valueErrorMinus = valueErrorMinus[i];
14732 newData.valueErrorMinus = valueErrorMinus[i];
14752 newData.valueErrorPlus = valueErrorPlus[i];
14733 newData.valueErrorPlus = valueErrorPlus[i];
14753 mData->insertMulti(key[i], newData);
14734 mData->insertMulti(key[i], newData);
14754 }
14735 }
14755 }
14736 }
14756
14737
@@ -14763,7 +14744,7 void QCPGraph::setDataBothError(const QV
14763 */
14744 */
14764 void QCPGraph::setLineStyle(LineStyle ls)
14745 void QCPGraph::setLineStyle(LineStyle ls)
14765 {
14746 {
14766 mLineStyle = ls;
14747 mLineStyle = ls;
14767 }
14748 }
14768
14749
14769 /*!
14750 /*!
@@ -14774,7 +14755,7 void QCPGraph::setLineStyle(LineStyle ls
14774 */
14755 */
14775 void QCPGraph::setScatterStyle(const QCPScatterStyle &style)
14756 void QCPGraph::setScatterStyle(const QCPScatterStyle &style)
14776 {
14757 {
14777 mScatterStyle = style;
14758 mScatterStyle = style;
14778 }
14759 }
14779
14760
14780 /*!
14761 /*!
@@ -14787,7 +14768,7 void QCPGraph::setScatterStyle(const QCP
14787 */
14768 */
14788 void QCPGraph::setErrorType(ErrorType errorType)
14769 void QCPGraph::setErrorType(ErrorType errorType)
14789 {
14770 {
14790 mErrorType = errorType;
14771 mErrorType = errorType;
14791 }
14772 }
14792
14773
14793 /*!
14774 /*!
@@ -14796,7 +14777,7 void QCPGraph::setErrorType(ErrorType er
14796 */
14777 */
14797 void QCPGraph::setErrorPen(const QPen &pen)
14778 void QCPGraph::setErrorPen(const QPen &pen)
14798 {
14779 {
14799 mErrorPen = pen;
14780 mErrorPen = pen;
14800 }
14781 }
14801
14782
14802 /*!
14783 /*!
@@ -14804,7 +14785,7 void QCPGraph::setErrorPen(const QPen &p
14804 */
14785 */
14805 void QCPGraph::setErrorBarSize(double size)
14786 void QCPGraph::setErrorBarSize(double size)
14806 {
14787 {
14807 mErrorBarSize = size;
14788 mErrorBarSize = size;
14808 }
14789 }
14809
14790
14810 /*!
14791 /*!
@@ -14820,7 +14801,7 void QCPGraph::setErrorBarSize(double si
14820 */
14801 */
14821 void QCPGraph::setErrorBarSkipSymbol(bool enabled)
14802 void QCPGraph::setErrorBarSkipSymbol(bool enabled)
14822 {
14803 {
14823 mErrorBarSkipSymbol = enabled;
14804 mErrorBarSkipSymbol = enabled;
14824 }
14805 }
14825
14806
14826 /*!
14807 /*!
@@ -14834,22 +14815,22 void QCPGraph::setErrorBarSkipSymbol(boo
14834 */
14815 */
14835 void QCPGraph::setChannelFillGraph(QCPGraph *targetGraph)
14816 void QCPGraph::setChannelFillGraph(QCPGraph *targetGraph)
14836 {
14817 {
14837 // prevent setting channel target to this graph itself:
14818 // prevent setting channel target to this graph itself:
14838 if (targetGraph == this)
14819 if (targetGraph == this)
14839 {
14820 {
14840 qDebug() << Q_FUNC_INFO << "targetGraph is this graph itself";
14821 qDebug() << Q_FUNC_INFO << "targetGraph is this graph itself";
14841 mChannelFillGraph = 0;
14822 mChannelFillGraph = 0;
14842 return;
14823 return;
14843 }
14824 }
14844 // prevent setting channel target to a graph not in the plot:
14825 // prevent setting channel target to a graph not in the plot:
14845 if (targetGraph && targetGraph->mParentPlot != mParentPlot)
14826 if (targetGraph && targetGraph->mParentPlot != mParentPlot)
14846 {
14827 {
14847 qDebug() << Q_FUNC_INFO << "targetGraph not in same plot";
14828 qDebug() << Q_FUNC_INFO << "targetGraph not in same plot";
14848 mChannelFillGraph = 0;
14829 mChannelFillGraph = 0;
14849 return;
14830 return;
14850 }
14831 }
14851
14832
14852 mChannelFillGraph = targetGraph;
14833 mChannelFillGraph = targetGraph;
14853 }
14834 }
14854
14835
14855 /*!
14836 /*!
@@ -14885,12 +14866,7 void QCPGraph::setChannelFillGraph(QCPGr
14885 */
14866 */
14886 void QCPGraph::setAdaptiveSampling(bool enabled)
14867 void QCPGraph::setAdaptiveSampling(bool enabled)
14887 {
14868 {
14888 mAdaptiveSampling = enabled;
14869 mAdaptiveSampling = enabled;
14889 }
14890
14891 void QCPGraph::setUseFastVectors(bool useFastVectors)
14892 {
14893 mUseFastVectors=useFastVectors;
14894 }
14870 }
14895
14871
14896 /*!
14872 /*!
@@ -14903,7 +14879,7 void QCPGraph::setUseFastVectors(bool us
14903 */
14879 */
14904 void QCPGraph::addData(const QCPDataMap &dataMap)
14880 void QCPGraph::addData(const QCPDataMap &dataMap)
14905 {
14881 {
14906 mData->unite(dataMap);
14882 mData->unite(dataMap);
14907 }
14883 }
14908
14884
14909 /*! \overload
14885 /*! \overload
@@ -14916,7 +14892,7 void QCPGraph::addData(const QCPDataMap
14916 */
14892 */
14917 void QCPGraph::addData(const QCPData &data)
14893 void QCPGraph::addData(const QCPData &data)
14918 {
14894 {
14919 mData->insertMulti(data.key, data);
14895 mData->insertMulti(data.key, data);
14920 }
14896 }
14921
14897
14922 /*! \overload
14898 /*! \overload
@@ -14929,10 +14905,10 void QCPGraph::addData(const QCPData &da
14929 */
14905 */
14930 void QCPGraph::addData(double key, double value)
14906 void QCPGraph::addData(double key, double value)
14931 {
14907 {
14932 QCPData newData;
14908 QCPData newData;
14933 newData.key = key;
14909 newData.key = key;
14934 newData.value = value;
14910 newData.value = value;
14935 mData->insertMulti(newData.key, newData);
14911 mData->insertMulti(newData.key, newData);
14936 }
14912 }
14937
14913
14938 /*! \overload
14914 /*! \overload
@@ -14945,13 +14921,13 void QCPGraph::addData(double key, doubl
14945 */
14921 */
14946 void QCPGraph::addData(const QVector<double> &keys, const QVector<double> &values)
14922 void QCPGraph::addData(const QVector<double> &keys, const QVector<double> &values)
14947 {
14923 {
14948 int n = qMin(keys.size(), values.size());
14924 int n = qMin(keys.size(), values.size());
14949 QCPData newData;
14925 QCPData newData;
14950 for (int i=0; i<n; ++i)
14926 for (int i=0; i<n; ++i)
14951 {
14927 {
14952 newData.key = keys[i];
14928 newData.key = keys[i];
14953 newData.value = values[i];
14929 newData.value = values[i];
14954 mData->insertMulti(newData.key, newData);
14930 mData->insertMulti(newData.key, newData);
14955 }
14931 }
14956 }
14932 }
14957
14933
@@ -14961,9 +14937,9 void QCPGraph::addData(const QVector<dou
14961 */
14937 */
14962 void QCPGraph::removeDataBefore(double key)
14938 void QCPGraph::removeDataBefore(double key)
14963 {
14939 {
14964 QCPDataMap::iterator it = mData->begin();
14940 QCPDataMap::iterator it = mData->begin();
14965 while (it != mData->end() && it.key() < key)
14941 while (it != mData->end() && it.key() < key)
14966 it = mData->erase(it);
14942 it = mData->erase(it);
14967 }
14943 }
14968
14944
14969 /*!
14945 /*!
@@ -14972,10 +14948,10 void QCPGraph::removeDataBefore(double k
14972 */
14948 */
14973 void QCPGraph::removeDataAfter(double key)
14949 void QCPGraph::removeDataAfter(double key)
14974 {
14950 {
14975 if (mData->isEmpty()) return;
14951 if (mData->isEmpty()) return;
14976 QCPDataMap::iterator it = mData->upperBound(key);
14952 QCPDataMap::iterator it = mData->upperBound(key);
14977 while (it != mData->end())
14953 while (it != mData->end())
14978 it = mData->erase(it);
14954 it = mData->erase(it);
14979 }
14955 }
14980
14956
14981 /*!
14957 /*!
@@ -14987,11 +14963,11 void QCPGraph::removeDataAfter(double ke
14987 */
14963 */
14988 void QCPGraph::removeData(double fromKey, double toKey)
14964 void QCPGraph::removeData(double fromKey, double toKey)
14989 {
14965 {
14990 if (fromKey >= toKey || mData->isEmpty()) return;
14966 if (fromKey >= toKey || mData->isEmpty()) return;
14991 QCPDataMap::iterator it = mData->upperBound(fromKey);
14967 QCPDataMap::iterator it = mData->upperBound(fromKey);
14992 QCPDataMap::iterator itEnd = mData->upperBound(toKey);
14968 QCPDataMap::iterator itEnd = mData->upperBound(toKey);
14993 while (it != itEnd)
14969 while (it != itEnd)
14994 it = mData->erase(it);
14970 it = mData->erase(it);
14995 }
14971 }
14996
14972
14997 /*! \overload
14973 /*! \overload
@@ -15004,7 +14980,7 void QCPGraph::removeData(double fromKey
15004 */
14980 */
15005 void QCPGraph::removeData(double key)
14981 void QCPGraph::removeData(double key)
15006 {
14982 {
15007 mData->remove(key);
14983 mData->remove(key);
15008 }
14984 }
15009
14985
15010 /*!
14986 /*!
@@ -15013,21 +14989,21 void QCPGraph::removeData(double key)
15013 */
14989 */
15014 void QCPGraph::clearData()
14990 void QCPGraph::clearData()
15015 {
14991 {
15016 mData->clear();
14992 mData->clear();
15017 }
14993 }
15018
14994
15019 /* inherits documentation from base class */
14995 /* inherits documentation from base class */
15020 double QCPGraph::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
14996 double QCPGraph::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
15021 {
14997 {
15022 Q_UNUSED(details)
14998 Q_UNUSED(details)
15023 if ((onlySelectable && !mSelectable) || mData->isEmpty())
14999 if ((onlySelectable && !mSelectable) || mData->isEmpty())
15024 return -1;
15000 return -1;
15025 if (!mKeyAxis || !mValueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return -1; }
15001 if (!mKeyAxis || !mValueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return -1; }
15026
15002
15027 if (mKeyAxis.data()->axisRect()->rect().contains(pos.toPoint()))
15003 if (mKeyAxis.data()->axisRect()->rect().contains(pos.toPoint()))
15028 return pointDistance(pos);
15004 return pointDistance(pos);
15029 else
15005 else
15030 return -1;
15006 return -1;
15031 }
15007 }
15032
15008
15033 /*! \overload
15009 /*! \overload
@@ -15039,8 +15015,8 double QCPGraph::selectTest(const QPoint
15039 */
15015 */
15040 void QCPGraph::rescaleAxes(bool onlyEnlarge, bool includeErrorBars) const
15016 void QCPGraph::rescaleAxes(bool onlyEnlarge, bool includeErrorBars) const
15041 {
15017 {
15042 rescaleKeyAxis(onlyEnlarge, includeErrorBars);
15018 rescaleKeyAxis(onlyEnlarge, includeErrorBars);
15043 rescaleValueAxis(onlyEnlarge, includeErrorBars);
15019 rescaleValueAxis(onlyEnlarge, includeErrorBars);
15044 }
15020 }
15045
15021
15046 /*! \overload
15022 /*! \overload
@@ -15052,30 +15028,30 void QCPGraph::rescaleAxes(bool onlyEnla
15052 */
15028 */
15053 void QCPGraph::rescaleKeyAxis(bool onlyEnlarge, bool includeErrorBars) const
15029 void QCPGraph::rescaleKeyAxis(bool onlyEnlarge, bool includeErrorBars) const
15054 {
15030 {
15055 // this code is a copy of QCPAbstractPlottable::rescaleKeyAxis with the only change
15031 // this code is a copy of QCPAbstractPlottable::rescaleKeyAxis with the only change
15056 // that getKeyRange is passed the includeErrorBars value.
15032 // that getKeyRange is passed the includeErrorBars value.
15057 if (mData->isEmpty()) return;
15033 if (mData->isEmpty()) return;
15058
15034
15059 QCPAxis *keyAxis = mKeyAxis.data();
15035 QCPAxis *keyAxis = mKeyAxis.data();
15060 if (!keyAxis) { qDebug() << Q_FUNC_INFO << "invalid key axis"; return; }
15036 if (!keyAxis) { qDebug() << Q_FUNC_INFO << "invalid key axis"; return; }
15061
15037
15062 SignDomain signDomain = sdBoth;
15038 SignDomain signDomain = sdBoth;
15063 if (keyAxis->scaleType() == QCPAxis::stLogarithmic)
15039 if (keyAxis->scaleType() == QCPAxis::stLogarithmic)
15064 signDomain = (keyAxis->range().upper < 0 ? sdNegative : sdPositive);
15040 signDomain = (keyAxis->range().upper < 0 ? sdNegative : sdPositive);
15065
15041
15066 bool foundRange;
15042 bool foundRange;
15067 QCPRange newRange = getKeyRange(foundRange, signDomain, includeErrorBars);
15043 QCPRange newRange = getKeyRange(foundRange, signDomain, includeErrorBars);
15068
15044
15069 if (foundRange)
15045 if (foundRange)
15070 {
15046 {
15071 if (onlyEnlarge)
15047 if (onlyEnlarge)
15072 {
15048 {
15073 if (keyAxis->range().lower < newRange.lower)
15049 if (keyAxis->range().lower < newRange.lower)
15074 newRange.lower = keyAxis->range().lower;
15050 newRange.lower = keyAxis->range().lower;
15075 if (keyAxis->range().upper > newRange.upper)
15051 if (keyAxis->range().upper > newRange.upper)
15076 newRange.upper = keyAxis->range().upper;
15052 newRange.upper = keyAxis->range().upper;
15077 }
15053 }
15078 keyAxis->setRange(newRange);
15054 keyAxis->setRange(newRange);
15079 }
15055 }
15080 }
15056 }
15081
15057
@@ -15088,111 +15064,113 void QCPGraph::rescaleKeyAxis(bool onlyE
15088 */
15064 */
15089 void QCPGraph::rescaleValueAxis(bool onlyEnlarge, bool includeErrorBars) const
15065 void QCPGraph::rescaleValueAxis(bool onlyEnlarge, bool includeErrorBars) const
15090 {
15066 {
15091 // this code is a copy of QCPAbstractPlottable::rescaleValueAxis with the only change
15067 // this code is a copy of QCPAbstractPlottable::rescaleValueAxis with the only change
15092 // is that getValueRange is passed the includeErrorBars value.
15068 // is that getValueRange is passed the includeErrorBars value.
15093 if (mData->isEmpty()) return;
15069 if (mData->isEmpty()) return;
15094
15070
15095 QCPAxis *valueAxis = mValueAxis.data();
15071 QCPAxis *valueAxis = mValueAxis.data();
15096 if (!valueAxis) { qDebug() << Q_FUNC_INFO << "invalid value axis"; return; }
15072 if (!valueAxis) { qDebug() << Q_FUNC_INFO << "invalid value axis"; return; }
15097
15073
15098 SignDomain signDomain = sdBoth;
15074 SignDomain signDomain = sdBoth;
15099 if (valueAxis->scaleType() == QCPAxis::stLogarithmic)
15075 if (valueAxis->scaleType() == QCPAxis::stLogarithmic)
15100 signDomain = (valueAxis->range().upper < 0 ? sdNegative : sdPositive);
15076 signDomain = (valueAxis->range().upper < 0 ? sdNegative : sdPositive);
15101
15077
15102 bool foundRange;
15078 bool foundRange;
15103 QCPRange newRange = getValueRange(foundRange, signDomain, includeErrorBars);
15079 QCPRange newRange = getValueRange(foundRange, signDomain, includeErrorBars);
15104
15080
15105 if (foundRange)
15081 if (foundRange)
15106 {
15082 {
15107 if (onlyEnlarge)
15083 if (onlyEnlarge)
15108 {
15084 {
15109 if (valueAxis->range().lower < newRange.lower)
15085 if (valueAxis->range().lower < newRange.lower)
15110 newRange.lower = valueAxis->range().lower;
15086 newRange.lower = valueAxis->range().lower;
15111 if (valueAxis->range().upper > newRange.upper)
15087 if (valueAxis->range().upper > newRange.upper)
15112 newRange.upper = valueAxis->range().upper;
15088 newRange.upper = valueAxis->range().upper;
15113 }
15089 }
15114 valueAxis->setRange(newRange);
15090 valueAxis->setRange(newRange);
15115 }
15091 }
15116 }
15092 }
15117
15093
15118 /* inherits documentation from base class */
15094 /* inherits documentation from base class */
15119 void QCPGraph::draw(QCPPainter *painter)
15095 void QCPGraph::draw(QCPPainter *painter)
15120 {
15096 {
15121 if (!mKeyAxis || !mValueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
15097 if (!mKeyAxis || !mValueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
15122 if (mKeyAxis.data()->range().size() <= 0 || (mData->isEmpty() && mDataVector->isEmpty())) return;
15098 int test = mKeyAxis.data()->range().size();
15123 if (mLineStyle == lsNone && mScatterStyle.isNone()) return;
15099 test = mData->count();
15124
15100 if (mKeyAxis.data()->range().size() <= 0 || mData->isEmpty()) return;
15125 // allocate line and (if necessary) point vectors:
15101 if (mLineStyle == lsNone && mScatterStyle.isNone()) return;
15126 QVector<QPointF> *lineData = new QVector<QPointF>;
15102
15127 QVector<QCPData> *scatterData = 0;
15103 // allocate line and (if necessary) point vectors:
15128 if (!mScatterStyle.isNone())
15104 QVector<QPointF> *lineData = new QVector<QPointF>;
15129 scatterData = new QVector<QCPData>;
15105 QVector<QCPData> *scatterData = 0;
15130
15106 if (!mScatterStyle.isNone())
15131 // fill vectors with data appropriate to plot style:
15107 scatterData = new QVector<QCPData>;
15132 getPlotData(lineData, scatterData);
15108
15133
15109 // fill vectors with data appropriate to plot style:
15134 // check data validity if flag set:
15110 getPlotData(lineData, scatterData);
15111
15112 // check data validity if flag set:
15135 #ifdef QCUSTOMPLOT_CHECK_DATA
15113 #ifdef QCUSTOMPLOT_CHECK_DATA
15136 QCPDataMap::const_iterator it;
15114 QCPDataMap::const_iterator it;
15137 for (it = mData->constBegin(); it != mData->constEnd(); ++it)
15115 for (it = mData->constBegin(); it != mData->constEnd(); ++it)
15138 {
15116 {
15139 if (QCP::isInvalidData(it.value().key, it.value().value) ||
15117 if (QCP::isInvalidData(it.value().key, it.value().value) ||
15140 QCP::isInvalidData(it.value().keyErrorPlus, it.value().keyErrorMinus) ||
15118 QCP::isInvalidData(it.value().keyErrorPlus, it.value().keyErrorMinus) ||
15141 QCP::isInvalidData(it.value().valueErrorPlus, it.value().valueErrorPlus))
15119 QCP::isInvalidData(it.value().valueErrorPlus, it.value().valueErrorPlus))
15142 qDebug() << Q_FUNC_INFO << "Data point at" << it.key() << "invalid." << "Plottable name:" << name();
15120 qDebug() << Q_FUNC_INFO << "Data point at" << it.key() << "invalid." << "Plottable name:" << name();
15143 }
15121 }
15144 #endif
15122 #endif
15145
15123
15146 // draw fill of graph:
15124 // draw fill of graph:
15147 drawFill(painter, lineData);
15125 drawFill(painter, lineData);
15148
15126
15149 // draw line:
15127 // draw line:
15150 if (mLineStyle == lsImpulse)
15128 if (mLineStyle == lsImpulse)
15151 drawImpulsePlot(painter, lineData);
15129 drawImpulsePlot(painter, lineData);
15152 else if (mLineStyle != lsNone)
15130 else if (mLineStyle != lsNone)
15153 drawLinePlot(painter, lineData); // also step plots can be drawn as a line plot
15131 drawLinePlot(painter, lineData); // also step plots can be drawn as a line plot
15154
15132
15155 // draw scatters:
15133 // draw scatters:
15156 if (scatterData)
15134 if (scatterData)
15157 drawScatterPlot(painter, scatterData);
15135 drawScatterPlot(painter, scatterData);
15158
15136
15159 // free allocated line and point vectors:
15137 // free allocated line and point vectors:
15160 delete lineData;
15138 delete lineData;
15161 if (scatterData)
15139 if (scatterData)
15162 delete scatterData;
15140 delete scatterData;
15163 }
15141 }
15164
15142
15165 /* inherits documentation from base class */
15143 /* inherits documentation from base class */
15166 void QCPGraph::drawLegendIcon(QCPPainter *painter, const QRectF &rect) const
15144 void QCPGraph::drawLegendIcon(QCPPainter *painter, const QRectF &rect) const
15167 {
15145 {
15168 // draw fill:
15146 // draw fill:
15169 if (mBrush.style() != Qt::NoBrush)
15147 if (mBrush.style() != Qt::NoBrush)
15170 {
15148 {
15171 applyFillAntialiasingHint(painter);
15149 applyFillAntialiasingHint(painter);
15172 painter->fillRect(QRectF(rect.left(), rect.top()+rect.height()/2.0, rect.width(), rect.height()/3.0), mBrush);
15150 painter->fillRect(QRectF(rect.left(), rect.top()+rect.height()/2.0, rect.width(), rect.height()/3.0), mBrush);
15173 }
15151 }
15174 // draw line vertically centered:
15152 // draw line vertically centered:
15175 if (mLineStyle != lsNone)
15153 if (mLineStyle != lsNone)
15176 {
15154 {
15177 applyDefaultAntialiasingHint(painter);
15155 applyDefaultAntialiasingHint(painter);
15178 painter->setPen(mPen);
15156 painter->setPen(mPen);
15179 painter->drawLine(QLineF(rect.left(), rect.top()+rect.height()/2.0, rect.right()+5, rect.top()+rect.height()/2.0)); // +5 on x2 else last segment is missing from dashed/dotted pens
15157 painter->drawLine(QLineF(rect.left(), rect.top()+rect.height()/2.0, rect.right()+5, rect.top()+rect.height()/2.0)); // +5 on x2 else last segment is missing from dashed/dotted pens
15180 }
15158 }
15181 // draw scatter symbol:
15159 // draw scatter symbol:
15182 if (!mScatterStyle.isNone())
15160 if (!mScatterStyle.isNone())
15183 {
15161 {
15184 applyScattersAntialiasingHint(painter);
15162 applyScattersAntialiasingHint(painter);
15185 // scale scatter pixmap if it's too large to fit in legend icon rect:
15163 // scale scatter pixmap if it's too large to fit in legend icon rect:
15186 if (mScatterStyle.shape() == QCPScatterStyle::ssPixmap && (mScatterStyle.pixmap().size().width() > rect.width() || mScatterStyle.pixmap().size().height() > rect.height()))
15164 if (mScatterStyle.shape() == QCPScatterStyle::ssPixmap && (mScatterStyle.pixmap().size().width() > rect.width() || mScatterStyle.pixmap().size().height() > rect.height()))
15187 {
15165 {
15188 QCPScatterStyle scaledStyle(mScatterStyle);
15166 QCPScatterStyle scaledStyle(mScatterStyle);
15189 scaledStyle.setPixmap(scaledStyle.pixmap().scaled(rect.size().toSize(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
15167 scaledStyle.setPixmap(scaledStyle.pixmap().scaled(rect.size().toSize(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
15190 scaledStyle.applyTo(painter, mPen);
15168 scaledStyle.applyTo(painter, mPen);
15191 scaledStyle.drawShape(painter, QRectF(rect).center());
15169 scaledStyle.drawShape(painter, QRectF(rect).center());
15192 } else
15170 } else
15193 {
15171 {
15194 mScatterStyle.applyTo(painter, mPen);
15172 mScatterStyle.applyTo(painter, mPen);
15195 mScatterStyle.drawShape(painter, QRectF(rect).center());
15173 mScatterStyle.drawShape(painter, QRectF(rect).center());
15196 }
15174 }
15197 }
15175 }
15198 }
15176 }
@@ -15217,7 +15195,7 void QCPGraph::drawLegendIcon(QCPPainter
15217 */
15195 */
15218 void QCPGraph::getPlotData(QVector<QPointF> *lineData, QVector<QCPData> *scatterData) const
15196 void QCPGraph::getPlotData(QVector<QPointF> *lineData, QVector<QCPData> *scatterData) const
15219 {
15197 {
15220 switch(mLineStyle)
15198 switch(mLineStyle)
15221 {
15199 {
15222 case lsNone: getScatterPlotData(scatterData); break;
15200 case lsNone: getScatterPlotData(scatterData); break;
15223 case lsLine: getLinePlotData(lineData, scatterData); break;
15201 case lsLine: getLinePlotData(lineData, scatterData); break;
@@ -15241,7 +15219,7 void QCPGraph::getPlotData(QVector<QPoin
15241 */
15219 */
15242 void QCPGraph::getScatterPlotData(QVector<QCPData> *scatterData) const
15220 void QCPGraph::getScatterPlotData(QVector<QCPData> *scatterData) const
15243 {
15221 {
15244 getPreparedData(0, scatterData);
15222 getPreparedData(0, scatterData);
15245 }
15223 }
15246
15224
15247 /*! \internal
15225 /*! \internal
@@ -15257,33 +15235,30 void QCPGraph::getScatterPlotData(QVecto
15257 */
15235 */
15258 void QCPGraph::getLinePlotData(QVector<QPointF> *linePixelData, QVector<QCPData> *scatterData) const
15236 void QCPGraph::getLinePlotData(QVector<QPointF> *linePixelData, QVector<QCPData> *scatterData) const
15259 {
15237 {
15260 QCPAxis *keyAxis = mKeyAxis.data();
15238 QCPAxis *keyAxis = mKeyAxis.data();
15261 QCPAxis *valueAxis = mValueAxis.data();
15239 QCPAxis *valueAxis = mValueAxis.data();
15262 if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
15240 if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
15263 if (!linePixelData) { qDebug() << Q_FUNC_INFO << "null pointer passed as linePixelData"; return; }
15241 if (!linePixelData) { qDebug() << Q_FUNC_INFO << "null pointer passed as linePixelData"; return; }
15264
15242
15265 QVector<QCPData> lineData;
15243 QVector<QCPData> lineData;
15266 if(mUseFastVectors)
15267 getPreparedDataVector(&lineData, scatterData);
15268 else
15269 getPreparedData(&lineData, scatterData);
15244 getPreparedData(&lineData, scatterData);
15270 linePixelData->reserve(lineData.size()+2); // added 2 to reserve memory for lower/upper fill base points that might be needed for fill
15245 linePixelData->reserve(lineData.size()+2); // added 2 to reserve memory for lower/upper fill base points that might be needed for fill
15271 linePixelData->resize(lineData.size());
15246 linePixelData->resize(lineData.size());
15272
15247
15273 // transform lineData points to pixels:
15248 // transform lineData points to pixels:
15274 if (keyAxis->orientation() == Qt::Vertical)
15249 if (keyAxis->orientation() == Qt::Vertical)
15275 {
15250 {
15276 for (int i=0; i<lineData.size(); ++i)
15251 for (int i=0; i<lineData.size(); ++i)
15277 {
15252 {
15278 (*linePixelData)[i].setX(valueAxis->coordToPixel(lineData.at(i).value));
15253 (*linePixelData)[i].setX(valueAxis->coordToPixel(lineData.at(i).value));
15279 (*linePixelData)[i].setY(keyAxis->coordToPixel(lineData.at(i).key));
15254 (*linePixelData)[i].setY(keyAxis->coordToPixel(lineData.at(i).key));
15280 }
15255 }
15281 } else // key axis is horizontal
15256 } else // key axis is horizontal
15282 {
15257 {
15283 for (int i=0; i<lineData.size(); ++i)
15258 for (int i=0; i<lineData.size(); ++i)
15284 {
15259 {
15285 (*linePixelData)[i].setX(keyAxis->coordToPixel(lineData.at(i).key));
15260 (*linePixelData)[i].setX(keyAxis->coordToPixel(lineData.at(i).key));
15286 (*linePixelData)[i].setY(valueAxis->coordToPixel(lineData.at(i).value));
15261 (*linePixelData)[i].setY(valueAxis->coordToPixel(lineData.at(i).value));
15287 }
15262 }
15288 }
15263 }
15289 }
15264 }
@@ -15301,42 +15276,42 void QCPGraph::getLinePlotData(QVector<Q
15301 */
15276 */
15302 void QCPGraph::getStepLeftPlotData(QVector<QPointF> *linePixelData, QVector<QCPData> *scatterData) const
15277 void QCPGraph::getStepLeftPlotData(QVector<QPointF> *linePixelData, QVector<QCPData> *scatterData) const
15303 {
15278 {
15304 QCPAxis *keyAxis = mKeyAxis.data();
15279 QCPAxis *keyAxis = mKeyAxis.data();
15305 QCPAxis *valueAxis = mValueAxis.data();
15280 QCPAxis *valueAxis = mValueAxis.data();
15306 if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
15281 if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
15307 if (!linePixelData) { qDebug() << Q_FUNC_INFO << "null pointer passed as lineData"; return; }
15282 if (!linePixelData) { qDebug() << Q_FUNC_INFO << "null pointer passed as lineData"; return; }
15308
15283
15309 QVector<QCPData> lineData;
15284 QVector<QCPData> lineData;
15310 getPreparedData(&lineData, scatterData);
15285 getPreparedData(&lineData, scatterData);
15311 linePixelData->reserve(lineData.size()*2+2); // added 2 to reserve memory for lower/upper fill base points that might be needed for fill
15286 linePixelData->reserve(lineData.size()*2+2); // added 2 to reserve memory for lower/upper fill base points that might be needed for fill
15312 linePixelData->resize(lineData.size()*2);
15287 linePixelData->resize(lineData.size()*2);
15313
15288
15314 // calculate steps from lineData and transform to pixel coordinates:
15289 // calculate steps from lineData and transform to pixel coordinates:
15315 if (keyAxis->orientation() == Qt::Vertical)
15290 if (keyAxis->orientation() == Qt::Vertical)
15316 {
15291 {
15317 double lastValue = valueAxis->coordToPixel(lineData.first().value);
15292 double lastValue = valueAxis->coordToPixel(lineData.first().value);
15318 double key;
15293 double key;
15319 for (int i=0; i<lineData.size(); ++i)
15294 for (int i=0; i<lineData.size(); ++i)
15320 {
15295 {
15321 key = keyAxis->coordToPixel(lineData.at(i).key);
15296 key = keyAxis->coordToPixel(lineData.at(i).key);
15322 (*linePixelData)[i*2+0].setX(lastValue);
15297 (*linePixelData)[i*2+0].setX(lastValue);
15323 (*linePixelData)[i*2+0].setY(key);
15298 (*linePixelData)[i*2+0].setY(key);
15324 lastValue = valueAxis->coordToPixel(lineData.at(i).value);
15299 lastValue = valueAxis->coordToPixel(lineData.at(i).value);
15325 (*linePixelData)[i*2+1].setX(lastValue);
15300 (*linePixelData)[i*2+1].setX(lastValue);
15326 (*linePixelData)[i*2+1].setY(key);
15301 (*linePixelData)[i*2+1].setY(key);
15327 }
15302 }
15328 } else // key axis is horizontal
15303 } else // key axis is horizontal
15329 {
15304 {
15330 double lastValue = valueAxis->coordToPixel(lineData.first().value);
15305 double lastValue = valueAxis->coordToPixel(lineData.first().value);
15331 double key;
15306 double key;
15332 for (int i=0; i<lineData.size(); ++i)
15307 for (int i=0; i<lineData.size(); ++i)
15333 {
15308 {
15334 key = keyAxis->coordToPixel(lineData.at(i).key);
15309 key = keyAxis->coordToPixel(lineData.at(i).key);
15335 (*linePixelData)[i*2+0].setX(key);
15310 (*linePixelData)[i*2+0].setX(key);
15336 (*linePixelData)[i*2+0].setY(lastValue);
15311 (*linePixelData)[i*2+0].setY(lastValue);
15337 lastValue = valueAxis->coordToPixel(lineData.at(i).value);
15312 lastValue = valueAxis->coordToPixel(lineData.at(i).value);
15338 (*linePixelData)[i*2+1].setX(key);
15313 (*linePixelData)[i*2+1].setX(key);
15339 (*linePixelData)[i*2+1].setY(lastValue);
15314 (*linePixelData)[i*2+1].setY(lastValue);
15340 }
15315 }
15341 }
15316 }
15342 }
15317 }
@@ -15354,42 +15329,42 void QCPGraph::getStepLeftPlotData(QVect
15354 */
15329 */
15355 void QCPGraph::getStepRightPlotData(QVector<QPointF> *linePixelData, QVector<QCPData> *scatterData) const
15330 void QCPGraph::getStepRightPlotData(QVector<QPointF> *linePixelData, QVector<QCPData> *scatterData) const
15356 {
15331 {
15357 QCPAxis *keyAxis = mKeyAxis.data();
15332 QCPAxis *keyAxis = mKeyAxis.data();
15358 QCPAxis *valueAxis = mValueAxis.data();
15333 QCPAxis *valueAxis = mValueAxis.data();
15359 if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
15334 if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
15360 if (!linePixelData) { qDebug() << Q_FUNC_INFO << "null pointer passed as lineData"; return; }
15335 if (!linePixelData) { qDebug() << Q_FUNC_INFO << "null pointer passed as lineData"; return; }
15361
15336
15362 QVector<QCPData> lineData;
15337 QVector<QCPData> lineData;
15363 getPreparedData(&lineData, scatterData);
15338 getPreparedData(&lineData, scatterData);
15364 linePixelData->reserve(lineData.size()*2+2); // added 2 to reserve memory for lower/upper fill base points that might be needed for fill
15339 linePixelData->reserve(lineData.size()*2+2); // added 2 to reserve memory for lower/upper fill base points that might be needed for fill
15365 linePixelData->resize(lineData.size()*2);
15340 linePixelData->resize(lineData.size()*2);
15366
15341
15367 // calculate steps from lineData and transform to pixel coordinates:
15342 // calculate steps from lineData and transform to pixel coordinates:
15368 if (keyAxis->orientation() == Qt::Vertical)
15343 if (keyAxis->orientation() == Qt::Vertical)
15369 {
15344 {
15370 double lastKey = keyAxis->coordToPixel(lineData.first().key);
15345 double lastKey = keyAxis->coordToPixel(lineData.first().key);
15371 double value;
15346 double value;
15372 for (int i=0; i<lineData.size(); ++i)
15347 for (int i=0; i<lineData.size(); ++i)
15373 {
15348 {
15374 value = valueAxis->coordToPixel(lineData.at(i).value);
15349 value = valueAxis->coordToPixel(lineData.at(i).value);
15375 (*linePixelData)[i*2+0].setX(value);
15350 (*linePixelData)[i*2+0].setX(value);
15376 (*linePixelData)[i*2+0].setY(lastKey);
15351 (*linePixelData)[i*2+0].setY(lastKey);
15377 lastKey = keyAxis->coordToPixel(lineData.at(i).key);
15352 lastKey = keyAxis->coordToPixel(lineData.at(i).key);
15378 (*linePixelData)[i*2+1].setX(value);
15353 (*linePixelData)[i*2+1].setX(value);
15379 (*linePixelData)[i*2+1].setY(lastKey);
15354 (*linePixelData)[i*2+1].setY(lastKey);
15380 }
15355 }
15381 } else // key axis is horizontal
15356 } else // key axis is horizontal
15382 {
15357 {
15383 double lastKey = keyAxis->coordToPixel(lineData.first().key);
15358 double lastKey = keyAxis->coordToPixel(lineData.first().key);
15384 double value;
15359 double value;
15385 for (int i=0; i<lineData.size(); ++i)
15360 for (int i=0; i<lineData.size(); ++i)
15386 {
15361 {
15387 value = valueAxis->coordToPixel(lineData.at(i).value);
15362 value = valueAxis->coordToPixel(lineData.at(i).value);
15388 (*linePixelData)[i*2+0].setX(lastKey);
15363 (*linePixelData)[i*2+0].setX(lastKey);
15389 (*linePixelData)[i*2+0].setY(value);
15364 (*linePixelData)[i*2+0].setY(value);
15390 lastKey = keyAxis->coordToPixel(lineData.at(i).key);
15365 lastKey = keyAxis->coordToPixel(lineData.at(i).key);
15391 (*linePixelData)[i*2+1].setX(lastKey);
15366 (*linePixelData)[i*2+1].setX(lastKey);
15392 (*linePixelData)[i*2+1].setY(value);
15367 (*linePixelData)[i*2+1].setY(value);
15393 }
15368 }
15394 }
15369 }
15395 }
15370 }
@@ -15407,54 +15382,54 void QCPGraph::getStepRightPlotData(QVec
15407 */
15382 */
15408 void QCPGraph::getStepCenterPlotData(QVector<QPointF> *linePixelData, QVector<QCPData> *scatterData) const
15383 void QCPGraph::getStepCenterPlotData(QVector<QPointF> *linePixelData, QVector<QCPData> *scatterData) const
15409 {
15384 {
15410 QCPAxis *keyAxis = mKeyAxis.data();
15385 QCPAxis *keyAxis = mKeyAxis.data();
15411 QCPAxis *valueAxis = mValueAxis.data();
15386 QCPAxis *valueAxis = mValueAxis.data();
15412 if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
15387 if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
15413 if (!linePixelData) { qDebug() << Q_FUNC_INFO << "null pointer passed as lineData"; return; }
15388 if (!linePixelData) { qDebug() << Q_FUNC_INFO << "null pointer passed as lineData"; return; }
15414
15389
15415 QVector<QCPData> lineData;
15390 QVector<QCPData> lineData;
15416 getPreparedData(&lineData, scatterData);
15391 getPreparedData(&lineData, scatterData);
15417 linePixelData->reserve(lineData.size()*2+2); // added 2 to reserve memory for lower/upper fill base points that might be needed for fill
15392 linePixelData->reserve(lineData.size()*2+2); // added 2 to reserve memory for lower/upper fill base points that might be needed for fill
15418 linePixelData->resize(lineData.size()*2);
15393 linePixelData->resize(lineData.size()*2);
15419 // calculate steps from lineData and transform to pixel coordinates:
15394 // calculate steps from lineData and transform to pixel coordinates:
15420 if (keyAxis->orientation() == Qt::Vertical)
15395 if (keyAxis->orientation() == Qt::Vertical)
15421 {
15396 {
15422 double lastKey = keyAxis->coordToPixel(lineData.first().key);
15397 double lastKey = keyAxis->coordToPixel(lineData.first().key);
15423 double lastValue = valueAxis->coordToPixel(lineData.first().value);
15398 double lastValue = valueAxis->coordToPixel(lineData.first().value);
15424 double key;
15399 double key;
15425 (*linePixelData)[0].setX(lastValue);
15400 (*linePixelData)[0].setX(lastValue);
15426 (*linePixelData)[0].setY(lastKey);
15401 (*linePixelData)[0].setY(lastKey);
15427 for (int i=1; i<lineData.size(); ++i)
15402 for (int i=1; i<lineData.size(); ++i)
15428 {
15403 {
15429 key = (keyAxis->coordToPixel(lineData.at(i).key)+lastKey)*0.5;
15404 key = (keyAxis->coordToPixel(lineData.at(i).key)+lastKey)*0.5;
15430 (*linePixelData)[i*2-1].setX(lastValue);
15405 (*linePixelData)[i*2-1].setX(lastValue);
15431 (*linePixelData)[i*2-1].setY(key);
15406 (*linePixelData)[i*2-1].setY(key);
15432 lastValue = valueAxis->coordToPixel(lineData.at(i).value);
15407 lastValue = valueAxis->coordToPixel(lineData.at(i).value);
15433 lastKey = keyAxis->coordToPixel(lineData.at(i).key);
15408 lastKey = keyAxis->coordToPixel(lineData.at(i).key);
15434 (*linePixelData)[i*2+0].setX(lastValue);
15409 (*linePixelData)[i*2+0].setX(lastValue);
15435 (*linePixelData)[i*2+0].setY(key);
15410 (*linePixelData)[i*2+0].setY(key);
15436 }
15411 }
15437 (*linePixelData)[lineData.size()*2-1].setX(lastValue);
15412 (*linePixelData)[lineData.size()*2-1].setX(lastValue);
15438 (*linePixelData)[lineData.size()*2-1].setY(lastKey);
15413 (*linePixelData)[lineData.size()*2-1].setY(lastKey);
15439 } else // key axis is horizontal
15414 } else // key axis is horizontal
15440 {
15415 {
15441 double lastKey = keyAxis->coordToPixel(lineData.first().key);
15416 double lastKey = keyAxis->coordToPixel(lineData.first().key);
15442 double lastValue = valueAxis->coordToPixel(lineData.first().value);
15417 double lastValue = valueAxis->coordToPixel(lineData.first().value);
15443 double key;
15418 double key;
15444 (*linePixelData)[0].setX(lastKey);
15419 (*linePixelData)[0].setX(lastKey);
15445 (*linePixelData)[0].setY(lastValue);
15420 (*linePixelData)[0].setY(lastValue);
15446 for (int i=1; i<lineData.size(); ++i)
15421 for (int i=1; i<lineData.size(); ++i)
15447 {
15422 {
15448 key = (keyAxis->coordToPixel(lineData.at(i).key)+lastKey)*0.5;
15423 key = (keyAxis->coordToPixel(lineData.at(i).key)+lastKey)*0.5;
15449 (*linePixelData)[i*2-1].setX(key);
15424 (*linePixelData)[i*2-1].setX(key);
15450 (*linePixelData)[i*2-1].setY(lastValue);
15425 (*linePixelData)[i*2-1].setY(lastValue);
15451 lastValue = valueAxis->coordToPixel(lineData.at(i).value);
15426 lastValue = valueAxis->coordToPixel(lineData.at(i).value);
15452 lastKey = keyAxis->coordToPixel(lineData.at(i).key);
15427 lastKey = keyAxis->coordToPixel(lineData.at(i).key);
15453 (*linePixelData)[i*2+0].setX(key);
15428 (*linePixelData)[i*2+0].setX(key);
15454 (*linePixelData)[i*2+0].setY(lastValue);
15429 (*linePixelData)[i*2+0].setY(lastValue);
15455 }
15430 }
15456 (*linePixelData)[lineData.size()*2-1].setX(lastKey);
15431 (*linePixelData)[lineData.size()*2-1].setX(lastKey);
15457 (*linePixelData)[lineData.size()*2-1].setY(lastValue);
15432 (*linePixelData)[lineData.size()*2-1].setY(lastValue);
15458 }
15433 }
15459
15434
15460 }
15435 }
@@ -15472,39 +15447,39 void QCPGraph::getStepCenterPlotData(QVe
15472 */
15447 */
15473 void QCPGraph::getImpulsePlotData(QVector<QPointF> *linePixelData, QVector<QCPData> *scatterData) const
15448 void QCPGraph::getImpulsePlotData(QVector<QPointF> *linePixelData, QVector<QCPData> *scatterData) const
15474 {
15449 {
15475 QCPAxis *keyAxis = mKeyAxis.data();
15450 QCPAxis *keyAxis = mKeyAxis.data();
15476 QCPAxis *valueAxis = mValueAxis.data();
15451 QCPAxis *valueAxis = mValueAxis.data();
15477 if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
15452 if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
15478 if (!linePixelData) { qDebug() << Q_FUNC_INFO << "null pointer passed as linePixelData"; return; }
15453 if (!linePixelData) { qDebug() << Q_FUNC_INFO << "null pointer passed as linePixelData"; return; }
15479
15454
15480 QVector<QCPData> lineData;
15455 QVector<QCPData> lineData;
15481 getPreparedData(&lineData, scatterData);
15456 getPreparedData(&lineData, scatterData);
15482 linePixelData->resize(lineData.size()*2); // no need to reserve 2 extra points because impulse plot has no fill
15457 linePixelData->resize(lineData.size()*2); // no need to reserve 2 extra points because impulse plot has no fill
15483
15458
15484 // transform lineData points to pixels:
15459 // transform lineData points to pixels:
15485 if (keyAxis->orientation() == Qt::Vertical)
15460 if (keyAxis->orientation() == Qt::Vertical)
15486 {
15461 {
15487 double zeroPointX = valueAxis->coordToPixel(0);
15462 double zeroPointX = valueAxis->coordToPixel(0);
15488 double key;
15463 double key;
15489 for (int i=0; i<lineData.size(); ++i)
15464 for (int i=0; i<lineData.size(); ++i)
15490 {
15465 {
15491 key = keyAxis->coordToPixel(lineData.at(i).key);
15466 key = keyAxis->coordToPixel(lineData.at(i).key);
15492 (*linePixelData)[i*2+0].setX(zeroPointX);
15467 (*linePixelData)[i*2+0].setX(zeroPointX);
15493 (*linePixelData)[i*2+0].setY(key);
15468 (*linePixelData)[i*2+0].setY(key);
15494 (*linePixelData)[i*2+1].setX(valueAxis->coordToPixel(lineData.at(i).value));
15469 (*linePixelData)[i*2+1].setX(valueAxis->coordToPixel(lineData.at(i).value));
15495 (*linePixelData)[i*2+1].setY(key);
15470 (*linePixelData)[i*2+1].setY(key);
15496 }
15471 }
15497 } else // key axis is horizontal
15472 } else // key axis is horizontal
15498 {
15473 {
15499 double zeroPointY = valueAxis->coordToPixel(0);
15474 double zeroPointY = valueAxis->coordToPixel(0);
15500 double key;
15475 double key;
15501 for (int i=0; i<lineData.size(); ++i)
15476 for (int i=0; i<lineData.size(); ++i)
15502 {
15477 {
15503 key = keyAxis->coordToPixel(lineData.at(i).key);
15478 key = keyAxis->coordToPixel(lineData.at(i).key);
15504 (*linePixelData)[i*2+0].setX(key);
15479 (*linePixelData)[i*2+0].setX(key);
15505 (*linePixelData)[i*2+0].setY(zeroPointY);
15480 (*linePixelData)[i*2+0].setY(zeroPointY);
15506 (*linePixelData)[i*2+1].setX(key);
15481 (*linePixelData)[i*2+1].setX(key);
15507 (*linePixelData)[i*2+1].setY(valueAxis->coordToPixel(lineData.at(i).value));
15482 (*linePixelData)[i*2+1].setY(valueAxis->coordToPixel(lineData.at(i).value));
15508 }
15483 }
15509 }
15484 }
15510 }
15485 }
@@ -15524,24 +15499,24 void QCPGraph::getImpulsePlotData(QVecto
15524 */
15499 */
15525 void QCPGraph::drawFill(QCPPainter *painter, QVector<QPointF> *lineData) const
15500 void QCPGraph::drawFill(QCPPainter *painter, QVector<QPointF> *lineData) const
15526 {
15501 {
15527 if (mLineStyle == lsImpulse) return; // fill doesn't make sense for impulse plot
15502 if (mLineStyle == lsImpulse) return; // fill doesn't make sense for impulse plot
15528 if (mainBrush().style() == Qt::NoBrush || mainBrush().color().alpha() == 0) return;
15503 if (mainBrush().style() == Qt::NoBrush || mainBrush().color().alpha() == 0) return;
15529
15504
15530 applyFillAntialiasingHint(painter);
15505 applyFillAntialiasingHint(painter);
15531 if (!mChannelFillGraph)
15506 if (!mChannelFillGraph)
15532 {
15507 {
15533 // draw base fill under graph, fill goes all the way to the zero-value-line:
15508 // draw base fill under graph, fill goes all the way to the zero-value-line:
15534 addFillBasePoints(lineData);
15509 addFillBasePoints(lineData);
15535 painter->setPen(Qt::NoPen);
15510 painter->setPen(Qt::NoPen);
15536 painter->setBrush(mainBrush());
15511 painter->setBrush(mainBrush());
15537 painter->drawPolygon(QPolygonF(*lineData));
15512 painter->drawPolygon(QPolygonF(*lineData));
15538 removeFillBasePoints(lineData);
15513 removeFillBasePoints(lineData);
15539 } else
15514 } else
15540 {
15515 {
15541 // draw channel fill between this graph and mChannelFillGraph:
15516 // draw channel fill between this graph and mChannelFillGraph:
15542 painter->setPen(Qt::NoPen);
15517 painter->setPen(Qt::NoPen);
15543 painter->setBrush(mainBrush());
15518 painter->setBrush(mainBrush());
15544 painter->drawPolygon(getChannelFillPolygon(lineData));
15519 painter->drawPolygon(getChannelFillPolygon(lineData));
15545 }
15520 }
15546 }
15521 }
15547
15522
@@ -15556,39 +15531,39 void QCPGraph::drawFill(QCPPainter *pain
15556 */
15531 */
15557 void QCPGraph::drawScatterPlot(QCPPainter *painter, QVector<QCPData> *scatterData) const
15532 void QCPGraph::drawScatterPlot(QCPPainter *painter, QVector<QCPData> *scatterData) const
15558 {
15533 {
15559 QCPAxis *keyAxis = mKeyAxis.data();
15534 QCPAxis *keyAxis = mKeyAxis.data();
15560 QCPAxis *valueAxis = mValueAxis.data();
15535 QCPAxis *valueAxis = mValueAxis.data();
15561 if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
15536 if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
15562
15537
15563 // draw error bars:
15538 // draw error bars:
15564 if (mErrorType != etNone)
15539 if (mErrorType != etNone)
15565 {
15540 {
15566 applyErrorBarsAntialiasingHint(painter);
15541 applyErrorBarsAntialiasingHint(painter);
15567 painter->setPen(mErrorPen);
15542 painter->setPen(mErrorPen);
15568 if (keyAxis->orientation() == Qt::Vertical)
15543 if (keyAxis->orientation() == Qt::Vertical)
15569 {
15544 {
15570 for (int i=0; i<scatterData->size(); ++i)
15545 for (int i=0; i<scatterData->size(); ++i)
15571 drawError(painter, valueAxis->coordToPixel(scatterData->at(i).value), keyAxis->coordToPixel(scatterData->at(i).key), scatterData->at(i));
15546 drawError(painter, valueAxis->coordToPixel(scatterData->at(i).value), keyAxis->coordToPixel(scatterData->at(i).key), scatterData->at(i));
15572 } else
15547 } else
15573 {
15548 {
15574 for (int i=0; i<scatterData->size(); ++i)
15549 for (int i=0; i<scatterData->size(); ++i)
15575 drawError(painter, keyAxis->coordToPixel(scatterData->at(i).key), valueAxis->coordToPixel(scatterData->at(i).value), scatterData->at(i));
15550 drawError(painter, keyAxis->coordToPixel(scatterData->at(i).key), valueAxis->coordToPixel(scatterData->at(i).value), scatterData->at(i));
15576 }
15551 }
15577 }
15552 }
15578
15553
15579 // draw scatter point symbols:
15554 // draw scatter point symbols:
15580 applyScattersAntialiasingHint(painter);
15555 applyScattersAntialiasingHint(painter);
15581 mScatterStyle.applyTo(painter, mPen);
15556 mScatterStyle.applyTo(painter, mPen);
15582 if (keyAxis->orientation() == Qt::Vertical)
15557 if (keyAxis->orientation() == Qt::Vertical)
15583 {
15558 {
15584 for (int i=0; i<scatterData->size(); ++i)
15559 for (int i=0; i<scatterData->size(); ++i)
15585 if (!qIsNaN(scatterData->at(i).value))
15560 if (!qIsNaN(scatterData->at(i).value))
15586 mScatterStyle.drawShape(painter, valueAxis->coordToPixel(scatterData->at(i).value), keyAxis->coordToPixel(scatterData->at(i).key));
15561 mScatterStyle.drawShape(painter, valueAxis->coordToPixel(scatterData->at(i).value), keyAxis->coordToPixel(scatterData->at(i).key));
15587 } else
15562 } else
15588 {
15563 {
15589 for (int i=0; i<scatterData->size(); ++i)
15564 for (int i=0; i<scatterData->size(); ++i)
15590 if (!qIsNaN(scatterData->at(i).value))
15565 if (!qIsNaN(scatterData->at(i).value))
15591 mScatterStyle.drawShape(painter, keyAxis->coordToPixel(scatterData->at(i).key), valueAxis->coordToPixel(scatterData->at(i).value));
15566 mScatterStyle.drawShape(painter, keyAxis->coordToPixel(scatterData->at(i).key), valueAxis->coordToPixel(scatterData->at(i).value));
15592 }
15567 }
15593 }
15568 }
15594
15569
@@ -15603,14 +15578,14 void QCPGraph::drawScatterPlot(QCPPainte
15603 */
15578 */
15604 void QCPGraph::drawLinePlot(QCPPainter *painter, QVector<QPointF> *lineData) const
15579 void QCPGraph::drawLinePlot(QCPPainter *painter, QVector<QPointF> *lineData) const
15605 {
15580 {
15606 // draw line of graph:
15581 // draw line of graph:
15607 if (mainPen().style() != Qt::NoPen && mainPen().color().alpha() != 0)
15582 if (mainPen().style() != Qt::NoPen && mainPen().color().alpha() != 0)
15608 {
15583 {
15609 applyDefaultAntialiasingHint(painter);
15584 applyDefaultAntialiasingHint(painter);
15610 painter->setPen(mainPen());
15585 painter->setPen(mainPen());
15611 painter->setBrush(Qt::NoBrush);
15586 painter->setBrush(Qt::NoBrush);
15612
15587
15613 /* Draws polyline in batches, currently not used:
15588 /* Draws polyline in batches, currently not used:
15614 int p = 0;
15589 int p = 0;
15615 while (p < lineData->size())
15590 while (p < lineData->size())
15616 {
15591 {
@@ -15625,38 +15600,38 void QCPGraph::drawLinePlot(QCPPainter *
15625 }
15600 }
15626 */
15601 */
15627
15602
15628 // if drawing solid line and not in PDF, use much faster line drawing instead of polyline:
15603 // if drawing solid line and not in PDF, use much faster line drawing instead of polyline:
15629 if (mParentPlot->plottingHints().testFlag(QCP::phFastPolylines) &&
15604 if (mParentPlot->plottingHints().testFlag(QCP::phFastPolylines) &&
15630 painter->pen().style() == Qt::SolidLine &&
15605 painter->pen().style() == Qt::SolidLine &&
15631 !painter->modes().testFlag(QCPPainter::pmVectorized)&&
15606 !painter->modes().testFlag(QCPPainter::pmVectorized)&&
15632 !painter->modes().testFlag(QCPPainter::pmNoCaching))
15607 !painter->modes().testFlag(QCPPainter::pmNoCaching))
15633 {
15608 {
15634 int i = 1;
15609 int i = 1;
15635 int lineDataSize = lineData->size();
15610 int lineDataSize = lineData->size();
15636 while (i < lineDataSize)
15611 while (i < lineDataSize)
15637 {
15612 {
15638 if (!qIsNaN(lineData->at(i).y()) && !qIsNaN(lineData->at(i).x())) // NaNs create a gap in the line
15613 if (!qIsNaN(lineData->at(i).y()) && !qIsNaN(lineData->at(i).x())) // NaNs create a gap in the line
15639 painter->drawLine(lineData->at(i-1), lineData->at(i));
15614 painter->drawLine(lineData->at(i-1), lineData->at(i));
15640 else
15615 else
15616 ++i;
15641 ++i;
15617 ++i;
15642 ++i;
15643 }
15618 }
15644 } else
15619 } else
15645 {
15620 {
15646 int segmentStart = 0;
15621 int segmentStart = 0;
15647 int i = 0;
15622 int i = 0;
15648 int lineDataSize = lineData->size();
15623 int lineDataSize = lineData->size();
15649 while (i < lineDataSize)
15624 while (i < lineDataSize)
15650 {
15625 {
15651 if (qIsNaN(lineData->at(i).y()) || qIsNaN(lineData->at(i).x())) // NaNs create a gap in the line
15626 if (qIsNaN(lineData->at(i).y()) || qIsNaN(lineData->at(i).x())) // NaNs create a gap in the line
15652 {
15627 {
15653 painter->drawPolyline(lineData->constData()+segmentStart, i-segmentStart); // i, because we don't want to include the current NaN point
15628 painter->drawPolyline(lineData->constData()+segmentStart, i-segmentStart); // i, because we don't want to include the current NaN point
15654 segmentStart = i+1;
15629 segmentStart = i+1;
15655 }
15630 }
15656 ++i;
15631 ++i;
15657 }
15632 }
15658 // draw last segment:
15633 // draw last segment:
15659 painter->drawPolyline(lineData->constData()+segmentStart, lineDataSize-segmentStart); // lineDataSize, because we do want to include the last point
15634 painter->drawPolyline(lineData->constData()+segmentStart, lineDataSize-segmentStart); // lineDataSize, because we do want to include the last point
15660 }
15635 }
15661 }
15636 }
15662 }
15637 }
@@ -15670,15 +15645,15 void QCPGraph::drawLinePlot(QCPPainter *
15670 */
15645 */
15671 void QCPGraph::drawImpulsePlot(QCPPainter *painter, QVector<QPointF> *lineData) const
15646 void QCPGraph::drawImpulsePlot(QCPPainter *painter, QVector<QPointF> *lineData) const
15672 {
15647 {
15673 // draw impulses:
15648 // draw impulses:
15674 if (mainPen().style() != Qt::NoPen && mainPen().color().alpha() != 0)
15649 if (mainPen().style() != Qt::NoPen && mainPen().color().alpha() != 0)
15675 {
15650 {
15676 applyDefaultAntialiasingHint(painter);
15651 applyDefaultAntialiasingHint(painter);
15677 QPen pen = mainPen();
15652 QPen pen = mainPen();
15678 pen.setCapStyle(Qt::FlatCap); // so impulse line doesn't reach beyond zero-line
15653 pen.setCapStyle(Qt::FlatCap); // so impulse line doesn't reach beyond zero-line
15679 painter->setPen(pen);
15654 painter->setPen(pen);
15680 painter->setBrush(Qt::NoBrush);
15655 painter->setBrush(Qt::NoBrush);
15681 painter->drawLines(*lineData);
15656 painter->drawLines(*lineData);
15682 }
15657 }
15683 }
15658 }
15684
15659
@@ -15696,368 +15671,182 void QCPGraph::drawImpulsePlot(QCPPainte
15696 */
15671 */
15697 void QCPGraph::getPreparedData(QVector<QCPData> *lineData, QVector<QCPData> *scatterData) const
15672 void QCPGraph::getPreparedData(QVector<QCPData> *lineData, QVector<QCPData> *scatterData) const
15698 {
15673 {
15699 QCPAxis *keyAxis = mKeyAxis.data();
15674 QCPAxis *keyAxis = mKeyAxis.data();
15700 QCPAxis *valueAxis = mValueAxis.data();
15675 QCPAxis *valueAxis = mValueAxis.data();
15701 if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
15676 if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
15702 // get visible data range:
15677 // get visible data range:
15703 QCPDataMap::const_iterator lower, upper; // note that upper is the actual upper point, and not 1 step after the upper point
15678 QCPDataMap::const_iterator lower, upper; // note that upper is the actual upper point, and not 1 step after the upper point
15704 getVisibleDataBounds(lower, upper);
15679 getVisibleDataBounds(lower, upper);
15705 if (lower == mData->constEnd() || upper == mData->constEnd())
15680 if (lower == mData->constEnd() || upper == mData->constEnd())
15706 return;
15681 return;
15707
15682
15708 // count points in visible range, taking into account that we only need to count to the limit maxCount if using adaptive sampling:
15683 // count points in visible range, taking into account that we only need to count to the limit maxCount if using adaptive sampling:
15709 int maxCount = std::numeric_limits<int>::max();
15684 int maxCount = std::numeric_limits<int>::max();
15710 if (mAdaptiveSampling)
15685 if (mAdaptiveSampling)
15711 {
15686 {
15712 int keyPixelSpan = qAbs(keyAxis->coordToPixel(lower.key())-keyAxis->coordToPixel(upper.key()));
15687 int keyPixelSpan = qAbs(keyAxis->coordToPixel(lower.key())-keyAxis->coordToPixel(upper.key()));
15713 maxCount = 2*keyPixelSpan+2;
15688 maxCount = 2*keyPixelSpan+2;
15714 }
15689 }
15715 int dataCount = countDataInBounds(lower, upper, maxCount);
15690 int dataCount = countDataInBounds(lower, upper, maxCount);
15716
15691
15717 if (mAdaptiveSampling && dataCount >= maxCount) // use adaptive sampling only if there are at least two points per pixel on average
15692 if (mAdaptiveSampling && dataCount >= maxCount) // use adaptive sampling only if there are at least two points per pixel on average
15718 {
15693 {
15719 if (lineData)
15694 if (lineData)
15720 {
15695 {
15721 QCPDataMap::const_iterator it = lower;
15696 QCPDataMap::const_iterator it = lower;
15722 QCPDataMap::const_iterator upperEnd = upper+1;
15697 QCPDataMap::const_iterator upperEnd = upper+1;
15723 double minValue = it.value().value;
15698 double minValue = it.value().value;
15724 double maxValue = it.value().value;
15699 double maxValue = it.value().value;
15725 QCPDataMap::const_iterator currentIntervalFirstPoint = it;
15700 QCPDataMap::const_iterator currentIntervalFirstPoint = it;
15726 int reversedFactor = keyAxis->rangeReversed() != (keyAxis->orientation()==Qt::Vertical) ? -1 : 1; // is used to calculate keyEpsilon pixel into the correct direction
15701 int reversedFactor = keyAxis->rangeReversed() != (keyAxis->orientation()==Qt::Vertical) ? -1 : 1; // is used to calculate keyEpsilon pixel into the correct direction
15727 int reversedRound = keyAxis->rangeReversed() != (keyAxis->orientation()==Qt::Vertical) ? 1 : 0; // is used to switch between floor (normal) and ceil (reversed) rounding of currentIntervalStartKey
15702 int reversedRound = keyAxis->rangeReversed() != (keyAxis->orientation()==Qt::Vertical) ? 1 : 0; // is used to switch between floor (normal) and ceil (reversed) rounding of currentIntervalStartKey
15728 double currentIntervalStartKey = keyAxis->pixelToCoord((int)(keyAxis->coordToPixel(lower.key())+reversedRound));
15703 double currentIntervalStartKey = keyAxis->pixelToCoord((int)(keyAxis->coordToPixel(lower.key())+reversedRound));
15729 double lastIntervalEndKey = currentIntervalStartKey;
15704 double lastIntervalEndKey = currentIntervalStartKey;
15730 double keyEpsilon = qAbs(currentIntervalStartKey-keyAxis->pixelToCoord(keyAxis->coordToPixel(currentIntervalStartKey)+1.0*reversedFactor)); // interval of one pixel on screen when mapped to plot key coordinates
15705 double keyEpsilon = qAbs(currentIntervalStartKey-keyAxis->pixelToCoord(keyAxis->coordToPixel(currentIntervalStartKey)+1.0*reversedFactor)); // interval of one pixel on screen when mapped to plot key coordinates
15731 bool keyEpsilonVariable = keyAxis->scaleType() == QCPAxis::stLogarithmic; // indicates whether keyEpsilon needs to be updated after every interval (for log axes)
15706 bool keyEpsilonVariable = keyAxis->scaleType() == QCPAxis::stLogarithmic; // indicates whether keyEpsilon needs to be updated after every interval (for log axes)
15732 int intervalDataCount = 1;
15707 int intervalDataCount = 1;
15733 ++it; // advance iterator to second data point because adaptive sampling works in 1 point retrospect
15708 ++it; // advance iterator to second data point because adaptive sampling works in 1 point retrospect
15734 while (it != upperEnd)
15709 while (it != upperEnd)
15735 {
15710 {
15736 if (it.key() < currentIntervalStartKey+keyEpsilon) // data point is still within same pixel, so skip it and expand value span of this cluster if necessary
15711 if (it.key() < currentIntervalStartKey+keyEpsilon) // data point is still within same pixel, so skip it and expand value span of this cluster if necessary
15737 {
15712 {
15738 if (it.value().value < minValue)
15713 if (it.value().value < minValue)
15739 minValue = it.value().value;
15714 minValue = it.value().value;
15740 else if (it.value().value > maxValue)
15715 else if (it.value().value > maxValue)
15741 maxValue = it.value().value;
15716 maxValue = it.value().value;
15742 ++intervalDataCount;
15717 ++intervalDataCount;
15743 } else // new pixel interval started
15718 } else // new pixel interval started
15744 {
15719 {
15745 if (intervalDataCount >= 2) // last pixel had multiple data points, consolidate them to a cluster
15720 if (intervalDataCount >= 2) // last pixel had multiple data points, consolidate them to a cluster
15746 {
15721 {
15747 if (lastIntervalEndKey < currentIntervalStartKey-keyEpsilon) // last point is further away, so first point of this cluster must be at a real data point
15722 if (lastIntervalEndKey < currentIntervalStartKey-keyEpsilon) // last point is further away, so first point of this cluster must be at a real data point
15748 lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.2, currentIntervalFirstPoint.value().value));
15723 lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.2, currentIntervalFirstPoint.value().value));
15749 lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.25, minValue));
15724 lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.25, minValue));
15750 lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.75, maxValue));
15725 lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.75, maxValue));
15751 if (it.key() > currentIntervalStartKey+keyEpsilon*2) // new pixel started further away from previous cluster, so make sure the last point of the cluster is at a real data point
15726 if (it.key() > currentIntervalStartKey+keyEpsilon*2) // new pixel started further away from previous cluster, so make sure the last point of the cluster is at a real data point
15752 lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.8, (it-1).value().value));
15727 lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.8, (it-1).value().value));
15753 } else
15728 } else
15754 lineData->append(QCPData(currentIntervalFirstPoint.key(), currentIntervalFirstPoint.value().value));
15729 lineData->append(QCPData(currentIntervalFirstPoint.key(), currentIntervalFirstPoint.value().value));
15755 lastIntervalEndKey = (it-1).value().key;
15730 lastIntervalEndKey = (it-1).value().key;
15756 minValue = it.value().value;
15731 minValue = it.value().value;
15757 maxValue = it.value().value;
15732 maxValue = it.value().value;
15758 currentIntervalFirstPoint = it;
15733 currentIntervalFirstPoint = it;
15759 currentIntervalStartKey = keyAxis->pixelToCoord((int)(keyAxis->coordToPixel(it.key())+reversedRound));
15734 currentIntervalStartKey = keyAxis->pixelToCoord((int)(keyAxis->coordToPixel(it.key())+reversedRound));
15760 if (keyEpsilonVariable)
15735 if (keyEpsilonVariable)
15761 keyEpsilon = qAbs(currentIntervalStartKey-keyAxis->pixelToCoord(keyAxis->coordToPixel(currentIntervalStartKey)+1.0*reversedFactor));
15736 keyEpsilon = qAbs(currentIntervalStartKey-keyAxis->pixelToCoord(keyAxis->coordToPixel(currentIntervalStartKey)+1.0*reversedFactor));
15762 intervalDataCount = 1;
15737 intervalDataCount = 1;
15763 }
15738 }
15764 ++it;
15739 ++it;
15765 }
15740 }
15766 // handle last interval:
15741 // handle last interval:
15767 if (intervalDataCount >= 2) // last pixel had multiple data points, consolidate them to a cluster
15742 if (intervalDataCount >= 2) // last pixel had multiple data points, consolidate them to a cluster
15768 {
15743 {
15769 if (lastIntervalEndKey < currentIntervalStartKey-keyEpsilon) // last point wasn't a cluster, so first point of this cluster must be at a real data point
15744 if (lastIntervalEndKey < currentIntervalStartKey-keyEpsilon) // last point wasn't a cluster, so first point of this cluster must be at a real data point
15770 lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.2, currentIntervalFirstPoint.value().value));
15745 lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.2, currentIntervalFirstPoint.value().value));
15771 lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.25, minValue));
15746 lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.25, minValue));
15772 lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.75, maxValue));
15747 lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.75, maxValue));
15773 } else
15748 } else
15774 lineData->append(QCPData(currentIntervalFirstPoint.key(), currentIntervalFirstPoint.value().value));
15749 lineData->append(QCPData(currentIntervalFirstPoint.key(), currentIntervalFirstPoint.value().value));
15775 }
15750 }
15776
15751
15777 if (scatterData)
15752 if (scatterData)
15778 {
15753 {
15779 double valueMaxRange = valueAxis->range().upper;
15754 double valueMaxRange = valueAxis->range().upper;
15780 double valueMinRange = valueAxis->range().lower;
15755 double valueMinRange = valueAxis->range().lower;
15781 QCPDataMap::const_iterator it = lower;
15756 QCPDataMap::const_iterator it = lower;
15782 QCPDataMap::const_iterator upperEnd = upper+1;
15757 QCPDataMap::const_iterator upperEnd = upper+1;
15783 double minValue = it.value().value;
15758 double minValue = it.value().value;
15784 double maxValue = it.value().value;
15759 double maxValue = it.value().value;
15785 QCPDataMap::const_iterator minValueIt = it;
15760 QCPDataMap::const_iterator minValueIt = it;
15786 QCPDataMap::const_iterator maxValueIt = it;
15761 QCPDataMap::const_iterator maxValueIt = it;
15787 QCPDataMap::const_iterator currentIntervalStart = it;
15762 QCPDataMap::const_iterator currentIntervalStart = it;
15788 int reversedFactor = keyAxis->rangeReversed() ? -1 : 1; // is used to calculate keyEpsilon pixel into the correct direction
15763 int reversedFactor = keyAxis->rangeReversed() ? -1 : 1; // is used to calculate keyEpsilon pixel into the correct direction
15789 int reversedRound = keyAxis->rangeReversed() ? 1 : 0; // is used to switch between floor (normal) and ceil (reversed) rounding of currentIntervalStartKey
15764 int reversedRound = keyAxis->rangeReversed() ? 1 : 0; // is used to switch between floor (normal) and ceil (reversed) rounding of currentIntervalStartKey
15790 double currentIntervalStartKey = keyAxis->pixelToCoord((int)(keyAxis->coordToPixel(lower.key())+reversedRound));
15765 double currentIntervalStartKey = keyAxis->pixelToCoord((int)(keyAxis->coordToPixel(lower.key())+reversedRound));
15791 double keyEpsilon = qAbs(currentIntervalStartKey-keyAxis->pixelToCoord(keyAxis->coordToPixel(currentIntervalStartKey)+1.0*reversedFactor)); // interval of one pixel on screen when mapped to plot key coordinates
15766 double keyEpsilon = qAbs(currentIntervalStartKey-keyAxis->pixelToCoord(keyAxis->coordToPixel(currentIntervalStartKey)+1.0*reversedFactor)); // interval of one pixel on screen when mapped to plot key coordinates
15792 bool keyEpsilonVariable = keyAxis->scaleType() == QCPAxis::stLogarithmic; // indicates whether keyEpsilon needs to be updated after every interval (for log axes)
15767 bool keyEpsilonVariable = keyAxis->scaleType() == QCPAxis::stLogarithmic; // indicates whether keyEpsilon needs to be updated after every interval (for log axes)
15793 int intervalDataCount = 1;
15768 int intervalDataCount = 1;
15794 ++it; // advance iterator to second data point because adaptive sampling works in 1 point retrospect
15769 ++it; // advance iterator to second data point because adaptive sampling works in 1 point retrospect
15795 while (it != upperEnd)
15770 while (it != upperEnd)
15796 {
15771 {
15797 if (it.key() < currentIntervalStartKey+keyEpsilon) // data point is still within same pixel, so skip it and expand value span of this pixel if necessary
15772 if (it.key() < currentIntervalStartKey+keyEpsilon) // data point is still within same pixel, so skip it and expand value span of this pixel if necessary
15798 {
15773 {
15799 if (it.value().value < minValue && it.value().value > valueMinRange && it.value().value < valueMaxRange)
15774 if (it.value().value < minValue && it.value().value > valueMinRange && it.value().value < valueMaxRange)
15800 {
15775 {
15801 minValue = it.value().value;
15776 minValue = it.value().value;
15802 minValueIt = it;
15777 minValueIt = it;
15803 } else if (it.value().value > maxValue && it.value().value > valueMinRange && it.value().value < valueMaxRange)
15778 } else if (it.value().value > maxValue && it.value().value > valueMinRange && it.value().value < valueMaxRange)
15804 {
15779 {
15805 maxValue = it.value().value;
15780 maxValue = it.value().value;
15806 maxValueIt = it;
15781 maxValueIt = it;
15807 }
15782 }
15808 ++intervalDataCount;
15783 ++intervalDataCount;
15809 } else // new pixel started
15784 } else // new pixel started
15810 {
15785 {
15811 if (intervalDataCount >= 2) // last pixel had multiple data points, consolidate them
15786 if (intervalDataCount >= 2) // last pixel had multiple data points, consolidate them
15812 {
15787 {
15813 // determine value pixel span and add as many points in interval to maintain certain vertical data density (this is specific to scatter plot):
15788 // determine value pixel span and add as many points in interval to maintain certain vertical data density (this is specific to scatter plot):
15814 double valuePixelSpan = qAbs(valueAxis->coordToPixel(minValue)-valueAxis->coordToPixel(maxValue));
15789 double valuePixelSpan = qAbs(valueAxis->coordToPixel(minValue)-valueAxis->coordToPixel(maxValue));
15815 int dataModulo = qMax(1, qRound(intervalDataCount/(valuePixelSpan/4.0))); // approximately every 4 value pixels one data point on average
15790 int dataModulo = qMax(1, qRound(intervalDataCount/(valuePixelSpan/4.0))); // approximately every 4 value pixels one data point on average
15816 QCPDataMap::const_iterator intervalIt = currentIntervalStart;
15791 QCPDataMap::const_iterator intervalIt = currentIntervalStart;
15817 int c = 0;
15792 int c = 0;
15818 while (intervalIt != it)
15793 while (intervalIt != it)
15819 {
15794 {
15820 if ((c % dataModulo == 0 || intervalIt == minValueIt || intervalIt == maxValueIt) && intervalIt.value().value > valueMinRange && intervalIt.value().value < valueMaxRange)
15795 if ((c % dataModulo == 0 || intervalIt == minValueIt || intervalIt == maxValueIt) && intervalIt.value().value > valueMinRange && intervalIt.value().value < valueMaxRange)
15821 scatterData->append(intervalIt.value());
15796 scatterData->append(intervalIt.value());
15822 ++c;
15797 ++c;
15823 ++intervalIt;
15798 ++intervalIt;
15824 }
15799 }
15825 } else if (currentIntervalStart.value().value > valueMinRange && currentIntervalStart.value().value < valueMaxRange)
15800 } else if (currentIntervalStart.value().value > valueMinRange && currentIntervalStart.value().value < valueMaxRange)
15826 scatterData->append(currentIntervalStart.value());
15801 scatterData->append(currentIntervalStart.value());
15827 minValue = it.value().value;
15802 minValue = it.value().value;
15828 maxValue = it.value().value;
15803 maxValue = it.value().value;
15829 currentIntervalStart = it;
15804 currentIntervalStart = it;
15830 currentIntervalStartKey = keyAxis->pixelToCoord((int)(keyAxis->coordToPixel(it.key())+reversedRound));
15805 currentIntervalStartKey = keyAxis->pixelToCoord((int)(keyAxis->coordToPixel(it.key())+reversedRound));
15831 if (keyEpsilonVariable)
15806 if (keyEpsilonVariable)
15832 keyEpsilon = qAbs(currentIntervalStartKey-keyAxis->pixelToCoord(keyAxis->coordToPixel(currentIntervalStartKey)+1.0*reversedFactor));
15807 keyEpsilon = qAbs(currentIntervalStartKey-keyAxis->pixelToCoord(keyAxis->coordToPixel(currentIntervalStartKey)+1.0*reversedFactor));
15833 intervalDataCount = 1;
15808 intervalDataCount = 1;
15834 }
15809 }
15835 ++it;
15810 ++it;
15836 }
15811 }
15837 // handle last interval:
15812 // handle last interval:
15838 if (intervalDataCount >= 2) // last pixel had multiple data points, consolidate them
15813 if (intervalDataCount >= 2) // last pixel had multiple data points, consolidate them
15839 {
15814 {
15840 // determine value pixel span and add as many points in interval to maintain certain vertical data density (this is specific to scatter plot):
15815 // determine value pixel span and add as many points in interval to maintain certain vertical data density (this is specific to scatter plot):
15841 double valuePixelSpan = qAbs(valueAxis->coordToPixel(minValue)-valueAxis->coordToPixel(maxValue));
15816 double valuePixelSpan = qAbs(valueAxis->coordToPixel(minValue)-valueAxis->coordToPixel(maxValue));
15842 int dataModulo = qMax(1, qRound(intervalDataCount/(valuePixelSpan/4.0))); // approximately every 4 value pixels one data point on average
15817 int dataModulo = qMax(1, qRound(intervalDataCount/(valuePixelSpan/4.0))); // approximately every 4 value pixels one data point on average
15843 QCPDataMap::const_iterator intervalIt = currentIntervalStart;
15818 QCPDataMap::const_iterator intervalIt = currentIntervalStart;
15844 int c = 0;
15819 int c = 0;
15845 while (intervalIt != it)
15820 while (intervalIt != it)
15846 {
15821 {
15847 if ((c % dataModulo == 0 || intervalIt == minValueIt || intervalIt == maxValueIt) && intervalIt.value().value > valueMinRange && intervalIt.value().value < valueMaxRange)
15822 if ((c % dataModulo == 0 || intervalIt == minValueIt || intervalIt == maxValueIt) && intervalIt.value().value > valueMinRange && intervalIt.value().value < valueMaxRange)
15848 scatterData->append(intervalIt.value());
15823 scatterData->append(intervalIt.value());
15849 ++c;
15824 ++c;
15850 ++intervalIt;
15825 ++intervalIt;
15851 }
15826 }
15852 } else if (currentIntervalStart.value().value > valueMinRange && currentIntervalStart.value().value < valueMaxRange)
15827 } else if (currentIntervalStart.value().value > valueMinRange && currentIntervalStart.value().value < valueMaxRange)
15853 scatterData->append(currentIntervalStart.value());
15828 scatterData->append(currentIntervalStart.value());
15854 }
15829 }
15855 } else // don't use adaptive sampling algorithm, transfer points one-to-one from the map into the output parameters
15830 } else // don't use adaptive sampling algorithm, transfer points one-to-one from the map into the output parameters
15856 {
15831 {
15857 QVector<QCPData> *dataVector = 0;
15832 QVector<QCPData> *dataVector = 0;
15858 if (lineData)
15833 if (lineData)
15859 {
15834 dataVector = lineData;
15860 dataVector = lineData;
15835 else if (scatterData)
15861 }
15836 dataVector = scatterData;
15862 else if (scatterData)
15837 if (dataVector)
15863 dataVector = scatterData;
15838 {
15864 if (dataVector)
15839 QCPDataMap::const_iterator it = lower;
15865 {
15840 QCPDataMap::const_iterator upperEnd = upper+1;
15866 QCPDataMap::const_iterator it = lower;
15841 dataVector->reserve(dataCount+2); // +2 for possible fill end points
15867 QCPDataMap::const_iterator upperEnd = upper+1;
15842 while (it != upperEnd)
15868 dataVector->reserve(dataCount+2); // +2 for possible fill end points
15843 {
15869 while (it != upperEnd)
15844 dataVector->append(it.value());
15870 {
15845 ++it;
15871 dataVector->append(it.value());
15846 }
15872 ++it;
15847 }
15873 }
15848 if (lineData && scatterData)
15874 }
15849 *scatterData = *dataVector;
15875 if (lineData && scatterData)
15876 *scatterData = *dataVector;
15877 }
15878 }
15879
15880
15881 void QCPGraph::getPreparedDataVector(QVector<QCPData> *lineData, QVector<QCPData> *scatterData) const
15882 {
15883 QCPAxis *keyAxis = mKeyAxis.data();
15884 QCPAxis *valueAxis = mValueAxis.data();
15885 if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
15886 // get visible data range:
15887 QVector<QCPData>::const_iterator lower, upper; // note that upper is the actual upper point, and not 1 step after the upper point
15888 getVisibleDataBoundsVector(lower, upper);
15889 if (lower == mDataVector->constEnd() || upper == mDataVector->constEnd())
15890 return;
15891
15892 // count points in visible range, taking into account that we only need to count to the limit maxCount if using adaptive sampling:
15893 int maxCount = std::numeric_limits<int>::max();
15894 if (mAdaptiveSampling)
15895 {
15896 int keyPixelSpan = qAbs(keyAxis->coordToPixel((*lower).key)-keyAxis->coordToPixel((*upper).key));
15897 maxCount = 2*keyPixelSpan+2;
15898 }
15899 int dataCount = countDataInBoundsVector(lower, upper, maxCount);
15900
15901 if (mAdaptiveSampling && dataCount >= maxCount) // use adaptive sampling only if there are at least two points per pixel on average
15902 {
15903 if (lineData)
15904 {
15905 QVector<QCPData>::const_iterator it = lower;
15906 QVector<QCPData>::const_iterator upperEnd = upper+1;
15907 double minValue = (*it).value;
15908 double maxValue = (*it).value;
15909 QVector<QCPData>::const_iterator currentIntervalFirstPoint = it;
15910 int reversedFactor = keyAxis->rangeReversed() != (keyAxis->orientation()==Qt::Vertical) ? -1 : 1; // is used to calculate keyEpsilon pixel into the correct direction
15911 int reversedRound = keyAxis->rangeReversed() != (keyAxis->orientation()==Qt::Vertical) ? 1 : 0; // is used to switch between floor (normal) and ceil (reversed) rounding of currentIntervalStartKey
15912 double currentIntervalStartKey = keyAxis->pixelToCoord((int)(keyAxis->coordToPixel((*lower).key)+reversedRound));
15913 double lastIntervalEndKey = currentIntervalStartKey;
15914 double keyEpsilon = qAbs(currentIntervalStartKey-keyAxis->pixelToCoord(keyAxis->coordToPixel(currentIntervalStartKey)+1.0*reversedFactor)); // interval of one pixel on screen when mapped to plot key coordinates
15915 bool keyEpsilonVariable = keyAxis->scaleType() == QCPAxis::stLogarithmic; // indicates whether keyEpsilon needs to be updated after every interval (for log axes)
15916 int intervalDataCount = 1;
15917 ++it; // advance iterator to second data point because adaptive sampling works in 1 point retrospect
15918 while (it != upperEnd)
15919 {
15920 if ((*it).key < currentIntervalStartKey+keyEpsilon) // data point is still within same pixel, so skip it and expand value span of this cluster if necessary
15921 {
15922 if ((*it).value < minValue)
15923 minValue = (*it).value;
15924 else if ((*it).value > maxValue)
15925 maxValue = (*it).value;
15926 ++intervalDataCount;
15927 } else // new pixel interval started
15928 {
15929 if (intervalDataCount >= 2) // last pixel had multiple data points, consolidate them to a cluster
15930 {
15931 if (lastIntervalEndKey < currentIntervalStartKey-keyEpsilon) // last point is further away, so first point of this cluster must be at a real data point
15932 lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.2, (*currentIntervalFirstPoint).value));
15933 lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.25, minValue));
15934 lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.75, maxValue));
15935 if ((*it).key > currentIntervalStartKey+keyEpsilon*2) // new pixel started further away from previous cluster, so make sure the last point of the cluster is at a real data point
15936 lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.8, (*(it-1)).value));
15937 } else
15938 lineData->append(QCPData((*currentIntervalFirstPoint).key, (*currentIntervalFirstPoint).value));
15939 lastIntervalEndKey = (*(it-1)).key;
15940 minValue = (*it).value;
15941 maxValue = (*it).value;
15942 currentIntervalFirstPoint = it;
15943 currentIntervalStartKey = keyAxis->pixelToCoord((int)(keyAxis->coordToPixel((*it).key)+reversedRound));
15944 if (keyEpsilonVariable)
15945 keyEpsilon = qAbs(currentIntervalStartKey-keyAxis->pixelToCoord(keyAxis->coordToPixel(currentIntervalStartKey)+1.0*reversedFactor));
15946 intervalDataCount = 1;
15947 }
15948 ++it;
15949 }
15950 // handle last interval:
15951 if (intervalDataCount >= 2) // last pixel had multiple data points, consolidate them to a cluster
15952 {
15953 if (lastIntervalEndKey < currentIntervalStartKey-keyEpsilon) // last point wasn't a cluster, so first point of this cluster must be at a real data point
15954 lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.2, (*currentIntervalFirstPoint).value));
15955 lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.25, minValue));
15956 lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.75, maxValue));
15957 } else
15958 lineData->append(QCPData((*currentIntervalFirstPoint).key, (*currentIntervalFirstPoint).value));
15959 }
15960
15961 if (scatterData)
15962 {
15963 double valueMaxRange = valueAxis->range().upper;
15964 double valueMinRange = valueAxis->range().lower;
15965 QVector<QCPData>::const_iterator it = lower;
15966 QVector<QCPData>::const_iterator upperEnd = upper+1;
15967 double minValue = (*it).value;
15968 double maxValue = (*it).value;
15969 QVector<QCPData>::const_iterator minValueIt = it;
15970 QVector<QCPData>::const_iterator maxValueIt = it;
15971 QVector<QCPData>::const_iterator currentIntervalStart = it;
15972 int reversedFactor = keyAxis->rangeReversed() ? -1 : 1; // is used to calculate keyEpsilon pixel into the correct direction
15973 int reversedRound = keyAxis->rangeReversed() ? 1 : 0; // is used to switch between floor (normal) and ceil (reversed) rounding of currentIntervalStartKey
15974 double currentIntervalStartKey = keyAxis->pixelToCoord((int)(keyAxis->coordToPixel((*lower).key)+reversedRound));
15975 double keyEpsilon = qAbs(currentIntervalStartKey-keyAxis->pixelToCoord(keyAxis->coordToPixel(currentIntervalStartKey)+1.0*reversedFactor)); // interval of one pixel on screen when mapped to plot key coordinates
15976 bool keyEpsilonVariable = keyAxis->scaleType() == QCPAxis::stLogarithmic; // indicates whether keyEpsilon needs to be updated after every interval (for log axes)
15977 int intervalDataCount = 1;
15978 ++it; // advance iterator to second data point because adaptive sampling works in 1 point retrospect
15979 while (it != upperEnd)
15980 {
15981 if ((*it).key < currentIntervalStartKey+keyEpsilon) // data point is still within same pixel, so skip it and expand value span of this pixel if necessary
15982 {
15983 if ((*it).value < minValue && (*it).value > valueMinRange && (*it).value < valueMaxRange)
15984 {
15985 minValue = (*it).value;
15986 minValueIt = it;
15987 } else if ((*it).value > maxValue && (*it).value > valueMinRange && (*it).value < valueMaxRange)
15988 {
15989 maxValue = (*it).value;
15990 maxValueIt = it;
15991 }
15992 ++intervalDataCount;
15993 } else // new pixel started
15994 {
15995 if (intervalDataCount >= 2) // last pixel had multiple data points, consolidate them
15996 {
15997 // determine value pixel span and add as many points in interval to maintain certain vertical data density (this is specific to scatter plot):
15998 double valuePixelSpan = qAbs(valueAxis->coordToPixel(minValue)-valueAxis->coordToPixel(maxValue));
15999 int dataModulo = qMax(1, qRound(intervalDataCount/(valuePixelSpan/4.0))); // approximately every 4 value pixels one data point on average
16000 QVector<QCPData>::const_iterator intervalIt = currentIntervalStart;
16001 int c = 0;
16002 while (intervalIt != it)
16003 {
16004 if ((c % dataModulo == 0 || intervalIt == minValueIt || intervalIt == maxValueIt) && (*intervalIt).value > valueMinRange && (*intervalIt).value < valueMaxRange)
16005 scatterData->append((*intervalIt));
16006 ++c;
16007 ++intervalIt;
16008 }
16009 } else if ((*currentIntervalStart).value > valueMinRange && (*currentIntervalStart).value < valueMaxRange)
16010 scatterData->append((*currentIntervalStart));
16011 minValue = (*it).value;
16012 maxValue = (*it).value;
16013 currentIntervalStart = it;
16014 currentIntervalStartKey = keyAxis->pixelToCoord((int)(keyAxis->coordToPixel((*it).key)+reversedRound));
16015 if (keyEpsilonVariable)
16016 keyEpsilon = qAbs(currentIntervalStartKey-keyAxis->pixelToCoord(keyAxis->coordToPixel(currentIntervalStartKey)+1.0*reversedFactor));
16017 intervalDataCount = 1;
16018 }
16019 ++it;
16020 }
16021 // handle last interval:
16022 if (intervalDataCount >= 2) // last pixel had multiple data points, consolidate them
16023 {
16024 // determine value pixel span and add as many points in interval to maintain certain vertical data density (this is specific to scatter plot):
16025 double valuePixelSpan = qAbs(valueAxis->coordToPixel(minValue)-valueAxis->coordToPixel(maxValue));
16026 int dataModulo = qMax(1, qRound(intervalDataCount/(valuePixelSpan/4.0))); // approximately every 4 value pixels one data point on average
16027 QVector<QCPData>::const_iterator intervalIt = currentIntervalStart;
16028 int c = 0;
16029 while (intervalIt != it)
16030 {
16031 if ((c % dataModulo == 0 || intervalIt == minValueIt || intervalIt == maxValueIt) && (*intervalIt).value > valueMinRange && (*intervalIt).value < valueMaxRange)
16032 scatterData->append((*intervalIt));
16033 ++c;
16034 ++intervalIt;
16035 }
16036 } else if ((*currentIntervalStart).value > valueMinRange && (*currentIntervalStart).value < valueMaxRange)
16037 scatterData->append(*currentIntervalStart);
16038 }
16039 } else // don't use adaptive sampling algorithm, transfer points one-to-one from the map into the output parameters
16040 {
16041 QVector<QCPData> *dataVector = 0;
16042 if (lineData)
16043 {
16044 dataVector = lineData;
16045 }
16046 else if (scatterData)
16047 dataVector = scatterData;
16048 if (dataVector)
16049 {
16050 QVector<QCPData>::const_iterator it = lower;
16051 QVector<QCPData>::const_iterator upperEnd = upper+1;
16052 dataVector->reserve(dataCount+2); // +2 for possible fill end points
16053 while (it != upperEnd)
16054 {
16055 dataVector->append(*it);
16056 ++it;
16057 }
16058 }
16059 if (lineData && scatterData)
16060 *scatterData = *dataVector;
16061 }
15850 }
16062 }
15851 }
16063
15852
@@ -16070,97 +15859,97 void QCPGraph::getPreparedDataVector(QVe
16070 */
15859 */
16071 void QCPGraph::drawError(QCPPainter *painter, double x, double y, const QCPData &data) const
15860 void QCPGraph::drawError(QCPPainter *painter, double x, double y, const QCPData &data) const
16072 {
15861 {
16073 if (qIsNaN(data.value))
15862 if (qIsNaN(data.value))
16074 return;
15863 return;
16075 QCPAxis *keyAxis = mKeyAxis.data();
15864 QCPAxis *keyAxis = mKeyAxis.data();
16076 QCPAxis *valueAxis = mValueAxis.data();
15865 QCPAxis *valueAxis = mValueAxis.data();
16077 if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
15866 if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
16078
15867
16079 double a, b; // positions of error bar bounds in pixels
15868 double a, b; // positions of error bar bounds in pixels
16080 double barWidthHalf = mErrorBarSize*0.5;
15869 double barWidthHalf = mErrorBarSize*0.5;
16081 double skipSymbolMargin = mScatterStyle.size(); // pixels left blank per side, when mErrorBarSkipSymbol is true
15870 double skipSymbolMargin = mScatterStyle.size(); // pixels left blank per side, when mErrorBarSkipSymbol is true
16082
15871
16083 if (keyAxis->orientation() == Qt::Vertical)
15872 if (keyAxis->orientation() == Qt::Vertical)
16084 {
15873 {
16085 // draw key error vertically and value error horizontally
15874 // draw key error vertically and value error horizontally
16086 if (mErrorType == etKey || mErrorType == etBoth)
15875 if (mErrorType == etKey || mErrorType == etBoth)
16087 {
15876 {
16088 a = keyAxis->coordToPixel(data.key-data.keyErrorMinus);
15877 a = keyAxis->coordToPixel(data.key-data.keyErrorMinus);
16089 b = keyAxis->coordToPixel(data.key+data.keyErrorPlus);
15878 b = keyAxis->coordToPixel(data.key+data.keyErrorPlus);
16090 if (keyAxis->rangeReversed())
15879 if (keyAxis->rangeReversed())
16091 qSwap(a,b);
15880 qSwap(a,b);
16092 // draw spine:
15881 // draw spine:
16093 if (mErrorBarSkipSymbol)
15882 if (mErrorBarSkipSymbol)
16094 {
15883 {
16095 if (a-y > skipSymbolMargin) // don't draw spine if error is so small it's within skipSymbolmargin
15884 if (a-y > skipSymbolMargin) // don't draw spine if error is so small it's within skipSymbolmargin
16096 painter->drawLine(QLineF(x, a, x, y+skipSymbolMargin));
15885 painter->drawLine(QLineF(x, a, x, y+skipSymbolMargin));
16097 if (y-b > skipSymbolMargin)
15886 if (y-b > skipSymbolMargin)
16098 painter->drawLine(QLineF(x, y-skipSymbolMargin, x, b));
15887 painter->drawLine(QLineF(x, y-skipSymbolMargin, x, b));
16099 } else
15888 } else
16100 painter->drawLine(QLineF(x, a, x, b));
15889 painter->drawLine(QLineF(x, a, x, b));
16101 // draw handles:
15890 // draw handles:
16102 painter->drawLine(QLineF(x-barWidthHalf, a, x+barWidthHalf, a));
15891 painter->drawLine(QLineF(x-barWidthHalf, a, x+barWidthHalf, a));
16103 painter->drawLine(QLineF(x-barWidthHalf, b, x+barWidthHalf, b));
15892 painter->drawLine(QLineF(x-barWidthHalf, b, x+barWidthHalf, b));
16104 }
15893 }
16105 if (mErrorType == etValue || mErrorType == etBoth)
15894 if (mErrorType == etValue || mErrorType == etBoth)
16106 {
15895 {
16107 a = valueAxis->coordToPixel(data.value-data.valueErrorMinus);
15896 a = valueAxis->coordToPixel(data.value-data.valueErrorMinus);
16108 b = valueAxis->coordToPixel(data.value+data.valueErrorPlus);
15897 b = valueAxis->coordToPixel(data.value+data.valueErrorPlus);
16109 if (valueAxis->rangeReversed())
15898 if (valueAxis->rangeReversed())
16110 qSwap(a,b);
15899 qSwap(a,b);
16111 // draw spine:
15900 // draw spine:
16112 if (mErrorBarSkipSymbol)
15901 if (mErrorBarSkipSymbol)
16113 {
15902 {
16114 if (x-a > skipSymbolMargin) // don't draw spine if error is so small it's within skipSymbolmargin
15903 if (x-a > skipSymbolMargin) // don't draw spine if error is so small it's within skipSymbolmargin
16115 painter->drawLine(QLineF(a, y, x-skipSymbolMargin, y));
15904 painter->drawLine(QLineF(a, y, x-skipSymbolMargin, y));
16116 if (b-x > skipSymbolMargin)
15905 if (b-x > skipSymbolMargin)
16117 painter->drawLine(QLineF(x+skipSymbolMargin, y, b, y));
15906 painter->drawLine(QLineF(x+skipSymbolMargin, y, b, y));
16118 } else
15907 } else
16119 painter->drawLine(QLineF(a, y, b, y));
15908 painter->drawLine(QLineF(a, y, b, y));
16120 // draw handles:
15909 // draw handles:
16121 painter->drawLine(QLineF(a, y-barWidthHalf, a, y+barWidthHalf));
15910 painter->drawLine(QLineF(a, y-barWidthHalf, a, y+barWidthHalf));
16122 painter->drawLine(QLineF(b, y-barWidthHalf, b, y+barWidthHalf));
15911 painter->drawLine(QLineF(b, y-barWidthHalf, b, y+barWidthHalf));
16123 }
15912 }
16124 } else // mKeyAxis->orientation() is Qt::Horizontal
15913 } else // mKeyAxis->orientation() is Qt::Horizontal
16125 {
15914 {
16126 // draw value error vertically and key error horizontally
15915 // draw value error vertically and key error horizontally
16127 if (mErrorType == etKey || mErrorType == etBoth)
15916 if (mErrorType == etKey || mErrorType == etBoth)
16128 {
15917 {
16129 a = keyAxis->coordToPixel(data.key-data.keyErrorMinus);
15918 a = keyAxis->coordToPixel(data.key-data.keyErrorMinus);
16130 b = keyAxis->coordToPixel(data.key+data.keyErrorPlus);
15919 b = keyAxis->coordToPixel(data.key+data.keyErrorPlus);
16131 if (keyAxis->rangeReversed())
15920 if (keyAxis->rangeReversed())
16132 qSwap(a,b);
15921 qSwap(a,b);
16133 // draw spine:
15922 // draw spine:
16134 if (mErrorBarSkipSymbol)
15923 if (mErrorBarSkipSymbol)
16135 {
15924 {
16136 if (x-a > skipSymbolMargin) // don't draw spine if error is so small it's within skipSymbolmargin
15925 if (x-a > skipSymbolMargin) // don't draw spine if error is so small it's within skipSymbolmargin
16137 painter->drawLine(QLineF(a, y, x-skipSymbolMargin, y));
15926 painter->drawLine(QLineF(a, y, x-skipSymbolMargin, y));
16138 if (b-x > skipSymbolMargin)
15927 if (b-x > skipSymbolMargin)
16139 painter->drawLine(QLineF(x+skipSymbolMargin, y, b, y));
15928 painter->drawLine(QLineF(x+skipSymbolMargin, y, b, y));
16140 } else
15929 } else
16141 painter->drawLine(QLineF(a, y, b, y));
15930 painter->drawLine(QLineF(a, y, b, y));
16142 // draw handles:
15931 // draw handles:
16143 painter->drawLine(QLineF(a, y-barWidthHalf, a, y+barWidthHalf));
15932 painter->drawLine(QLineF(a, y-barWidthHalf, a, y+barWidthHalf));
16144 painter->drawLine(QLineF(b, y-barWidthHalf, b, y+barWidthHalf));
15933 painter->drawLine(QLineF(b, y-barWidthHalf, b, y+barWidthHalf));
16145 }
15934 }
16146 if (mErrorType == etValue || mErrorType == etBoth)
15935 if (mErrorType == etValue || mErrorType == etBoth)
16147 {
15936 {
16148 a = valueAxis->coordToPixel(data.value-data.valueErrorMinus);
15937 a = valueAxis->coordToPixel(data.value-data.valueErrorMinus);
16149 b = valueAxis->coordToPixel(data.value+data.valueErrorPlus);
15938 b = valueAxis->coordToPixel(data.value+data.valueErrorPlus);
16150 if (valueAxis->rangeReversed())
15939 if (valueAxis->rangeReversed())
16151 qSwap(a,b);
15940 qSwap(a,b);
16152 // draw spine:
15941 // draw spine:
16153 if (mErrorBarSkipSymbol)
15942 if (mErrorBarSkipSymbol)
16154 {
15943 {
16155 if (a-y > skipSymbolMargin) // don't draw spine if error is so small it's within skipSymbolmargin
15944 if (a-y > skipSymbolMargin) // don't draw spine if error is so small it's within skipSymbolmargin
16156 painter->drawLine(QLineF(x, a, x, y+skipSymbolMargin));
15945 painter->drawLine(QLineF(x, a, x, y+skipSymbolMargin));
16157 if (y-b > skipSymbolMargin)
15946 if (y-b > skipSymbolMargin)
16158 painter->drawLine(QLineF(x, y-skipSymbolMargin, x, b));
15947 painter->drawLine(QLineF(x, y-skipSymbolMargin, x, b));
16159 } else
15948 } else
16160 painter->drawLine(QLineF(x, a, x, b));
15949 painter->drawLine(QLineF(x, a, x, b));
16161 // draw handles:
15950 // draw handles:
16162 painter->drawLine(QLineF(x-barWidthHalf, a, x+barWidthHalf, a));
15951 painter->drawLine(QLineF(x-barWidthHalf, a, x+barWidthHalf, a));
16163 painter->drawLine(QLineF(x-barWidthHalf, b, x+barWidthHalf, b));
15952 painter->drawLine(QLineF(x-barWidthHalf, b, x+barWidthHalf, b));
16164 }
15953 }
16165 }
15954 }
16166 }
15955 }
@@ -16181,93 +15970,22 void QCPGraph::drawError(QCPPainter *pai
16181 */
15970 */
16182 void QCPGraph::getVisibleDataBounds(QCPDataMap::const_iterator &lower, QCPDataMap::const_iterator &upper) const
15971 void QCPGraph::getVisibleDataBounds(QCPDataMap::const_iterator &lower, QCPDataMap::const_iterator &upper) const
16183 {
15972 {
16184 if (!mKeyAxis) { qDebug() << Q_FUNC_INFO << "invalid key axis"; return; }
15973 if (!mKeyAxis) { qDebug() << Q_FUNC_INFO << "invalid key axis"; return; }
16185 if (mData->isEmpty())
15974 if (mData->isEmpty())
16186 {
15975 {
16187 lower = mData->constEnd();
15976 lower = mData->constEnd();
16188 upper = mData->constEnd();
15977 upper = mData->constEnd();
16189 return;
15978 return;
16190 }
15979 }
16191
15980
16192 // get visible data range as QMap iterators
15981 // get visible data range as QMap iterators
16193 QCPDataMap::const_iterator lbound = mData->lowerBound(mKeyAxis.data()->range().lower);
15982 QCPDataMap::const_iterator lbound = mData->lowerBound(mKeyAxis.data()->range().lower);
16194 QCPDataMap::const_iterator ubound = mData->upperBound(mKeyAxis.data()->range().upper);
15983 QCPDataMap::const_iterator ubound = mData->upperBound(mKeyAxis.data()->range().upper);
16195 bool lowoutlier = lbound != mData->constBegin(); // indicates whether there exist points below axis range
15984 bool lowoutlier = lbound != mData->constBegin(); // indicates whether there exist points below axis range
16196 bool highoutlier = ubound != mData->constEnd(); // indicates whether there exist points above axis range
15985 bool highoutlier = ubound != mData->constEnd(); // indicates whether there exist points above axis range
16197
15986
16198 lower = (lowoutlier ? lbound-1 : lbound); // data point range that will be actually drawn
15987 lower = (lowoutlier ? lbound-1 : lbound); // data point range that will be actually drawn
16199 upper = (highoutlier ? ubound : ubound-1); // data point range that will be actually drawn
15988 upper = (highoutlier ? ubound : ubound-1); // data point range that will be actually drawn
16200 }
16201
16202
16203
16204
16205 QVector<QCPData>::const_iterator __lowerBoundDico(QVector<QCPData>* vector,double key)
16206 {
16207 int DX=vector->size()/2;
16208 int pos=DX;
16209 double test=(*vector)[vector->length()-1].key;
16210 if(key>((*vector)[vector->length()-1].key))
16211 return vector->constEnd();
16212 if(key<((*vector)[0].key))
16213 return vector->constBegin();
16214 while (DX>1)
16215 {
16216 DX=DX/2;
16217 if((*vector)[pos].key > key)
16218 {
16219 pos-=DX;
16220 }
16221 else
16222 {
16223 pos+=DX;
16224 }
16225 }
16226 if((*vector)[pos].key >= key)
16227 return vector->constBegin()+pos;
16228 return vector->constBegin()+pos+1;
16229 }
16230
16231
16232 QVector<QCPData>::const_iterator __upperBoundDico(QVector<QCPData>* vector,double key)
16233 {
16234 int DX=vector->size()/2;
16235 int pos=DX;
16236 if(key>((*vector)[vector->length()-1].key))
16237 return vector->constEnd();
16238 if(key<((*vector)[0].key))
16239 return vector->constBegin();
16240 while (DX>1)
16241 {
16242 DX=DX/2;
16243 if((*vector)[pos].key > key)
16244 {
16245 pos-=DX;
16246 }
16247 else
16248 {
16249 pos+=DX;
16250 }
16251 }
16252 return vector->constBegin()+pos+1;
16253 }
16254
16255 void QCPGraph::getVisibleDataBoundsVector(QVector<QCPData>::const_iterator &lower, QVector<QCPData>::const_iterator &upper) const
16256 {
16257 if (!mKeyAxis) { qDebug() << Q_FUNC_INFO << "invalid key axis"; return; }
16258 if (mDataVector->isEmpty())
16259 {
16260 lower = mDataVector->constEnd();
16261 upper = mDataVector->constEnd();
16262 return;
16263 }
16264 QVector<QCPData>::const_iterator lbound = __lowerBoundDico(mDataVector,mKeyAxis.data()->range().lower);
16265 QVector<QCPData>::const_iterator ubound = __upperBoundDico(mDataVector,mKeyAxis.data()->range().upper);
16266 bool lowoutlier = lbound != mDataVector->constBegin(); // indicates whether there exist points below axis range
16267 bool highoutlier = ubound != mDataVector->constEnd(); // indicates whether there exist points above axis range
16268
16269 lower = (lowoutlier ? lbound-1 : lbound); // data point range that will be actually drawn
16270 upper = (highoutlier ? ubound : ubound-1); // data point range that will be actually drawn
16271 }
15989 }
16272
15990
16273 /*! \internal
15991 /*! \internal
@@ -16282,30 +16000,16 void QCPGraph::getVisibleDataBoundsVecto
16282 */
16000 */
16283 int QCPGraph::countDataInBounds(const QCPDataMap::const_iterator &lower, const QCPDataMap::const_iterator &upper, int maxCount) const
16001 int QCPGraph::countDataInBounds(const QCPDataMap::const_iterator &lower, const QCPDataMap::const_iterator &upper, int maxCount) const
16284 {
16002 {
16285 if (upper == mData->constEnd() && lower == mData->constEnd())
16003 if (upper == mData->constEnd() && lower == mData->constEnd())
16286 return 0;
16004 return 0;
16287 QCPDataMap::const_iterator it = lower;
16005 QCPDataMap::const_iterator it = lower;
16288 int count = 1;
16006 int count = 1;
16289 while (it != upper && count < maxCount)
16007 while (it != upper && count < maxCount)
16290 {
16008 {
16291 ++it;
16009 ++it;
16292 ++count;
16010 ++count;
16293 }
16011 }
16294 return count;
16012 return count;
16295 }
16296
16297 int QCPGraph::countDataInBoundsVector(const QVector<QCPData>::const_iterator &lower, const QVector<QCPData>::const_iterator &upper, int maxCount) const
16298 {
16299 if (upper == mDataVector->constEnd() && lower == mDataVector->constEnd())
16300 return 0;
16301 QVector<QCPData>::const_iterator it = lower;
16302 int count = 1;
16303 while (it != upper && count < maxCount)
16304 {
16305 ++it;
16306 ++count;
16307 }
16308 return count;
16309 }
16013 }
16310
16014
16311 /*! \internal
16015 /*! \internal
@@ -16325,17 +16029,17 int QCPGraph::countDataInBoundsVector(co
16325 */
16029 */
16326 void QCPGraph::addFillBasePoints(QVector<QPointF> *lineData) const
16030 void QCPGraph::addFillBasePoints(QVector<QPointF> *lineData) const
16327 {
16031 {
16328 if (!mKeyAxis) { qDebug() << Q_FUNC_INFO << "invalid key axis"; return; }
16032 if (!mKeyAxis) { qDebug() << Q_FUNC_INFO << "invalid key axis"; return; }
16329
16033
16330 // append points that close the polygon fill at the key axis:
16034 // append points that close the polygon fill at the key axis:
16331 if (mKeyAxis.data()->orientation() == Qt::Vertical)
16035 if (mKeyAxis.data()->orientation() == Qt::Vertical)
16332 {
16036 {
16333 *lineData << upperFillBasePoint(lineData->last().y());
16037 *lineData << upperFillBasePoint(lineData->last().y());
16334 *lineData << lowerFillBasePoint(lineData->first().y());
16038 *lineData << lowerFillBasePoint(lineData->first().y());
16335 } else
16039 } else
16336 {
16040 {
16337 *lineData << upperFillBasePoint(lineData->last().x());
16041 *lineData << upperFillBasePoint(lineData->last().x());
16338 *lineData << lowerFillBasePoint(lineData->first().x());
16042 *lineData << lowerFillBasePoint(lineData->first().x());
16339 }
16043 }
16340 }
16044 }
16341
16045
@@ -16347,7 +16051,7 void QCPGraph::addFillBasePoints(QVector
16347 */
16051 */
16348 void QCPGraph::removeFillBasePoints(QVector<QPointF> *lineData) const
16052 void QCPGraph::removeFillBasePoints(QVector<QPointF> *lineData) const
16349 {
16053 {
16350 lineData->remove(lineData->size()-2, 2);
16054 lineData->remove(lineData->size()-2, 2);
16351 }
16055 }
16352
16056
16353 /*! \internal
16057 /*! \internal
@@ -16366,53 +16070,53 void QCPGraph::removeFillBasePoints(QVec
16366 */
16070 */
16367 QPointF QCPGraph::lowerFillBasePoint(double lowerKey) const
16071 QPointF QCPGraph::lowerFillBasePoint(double lowerKey) const
16368 {
16072 {
16369 QCPAxis *keyAxis = mKeyAxis.data();
16073 QCPAxis *keyAxis = mKeyAxis.data();
16370 QCPAxis *valueAxis = mValueAxis.data();
16074 QCPAxis *valueAxis = mValueAxis.data();
16371 if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return QPointF(); }
16075 if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return QPointF(); }
16372
16076
16373 QPointF point;
16077 QPointF point;
16374 if (valueAxis->scaleType() == QCPAxis::stLinear)
16078 if (valueAxis->scaleType() == QCPAxis::stLinear)
16375 {
16079 {
16376 if (keyAxis->axisType() == QCPAxis::atLeft)
16080 if (keyAxis->axisType() == QCPAxis::atLeft)
16377 {
16081 {
16378 point.setX(valueAxis->coordToPixel(0));
16082 point.setX(valueAxis->coordToPixel(0));
16379 point.setY(lowerKey);
16083 point.setY(lowerKey);
16380 } else if (keyAxis->axisType() == QCPAxis::atRight)
16084 } else if (keyAxis->axisType() == QCPAxis::atRight)
16381 {
16085 {
16382 point.setX(valueAxis->coordToPixel(0));
16086 point.setX(valueAxis->coordToPixel(0));
16383 point.setY(lowerKey);
16087 point.setY(lowerKey);
16384 } else if (keyAxis->axisType() == QCPAxis::atTop)
16088 } else if (keyAxis->axisType() == QCPAxis::atTop)
16385 {
16089 {
16386 point.setX(lowerKey);
16090 point.setX(lowerKey);
16387 point.setY(valueAxis->coordToPixel(0));
16091 point.setY(valueAxis->coordToPixel(0));
16388 } else if (keyAxis->axisType() == QCPAxis::atBottom)
16092 } else if (keyAxis->axisType() == QCPAxis::atBottom)
16389 {
16093 {
16390 point.setX(lowerKey);
16094 point.setX(lowerKey);
16391 point.setY(valueAxis->coordToPixel(0));
16095 point.setY(valueAxis->coordToPixel(0));
16392 }
16096 }
16393 } else // valueAxis->mScaleType == QCPAxis::stLogarithmic
16097 } else // valueAxis->mScaleType == QCPAxis::stLogarithmic
16394 {
16098 {
16395 // In logarithmic scaling we can't just draw to value zero so we just fill all the way
16099 // In logarithmic scaling we can't just draw to value zero so we just fill all the way
16396 // to the axis which is in the direction towards zero
16100 // to the axis which is in the direction towards zero
16397 if (keyAxis->orientation() == Qt::Vertical)
16101 if (keyAxis->orientation() == Qt::Vertical)
16398 {
16102 {
16399 if ((valueAxis->range().upper < 0 && !valueAxis->rangeReversed()) ||
16103 if ((valueAxis->range().upper < 0 && !valueAxis->rangeReversed()) ||
16400 (valueAxis->range().upper > 0 && valueAxis->rangeReversed())) // if range is negative, zero is on opposite side of key axis
16104 (valueAxis->range().upper > 0 && valueAxis->rangeReversed())) // if range is negative, zero is on opposite side of key axis
16401 point.setX(keyAxis->axisRect()->right());
16105 point.setX(keyAxis->axisRect()->right());
16402 else
16106 else
16403 point.setX(keyAxis->axisRect()->left());
16107 point.setX(keyAxis->axisRect()->left());
16404 point.setY(lowerKey);
16108 point.setY(lowerKey);
16405 } else if (keyAxis->axisType() == QCPAxis::atTop || keyAxis->axisType() == QCPAxis::atBottom)
16109 } else if (keyAxis->axisType() == QCPAxis::atTop || keyAxis->axisType() == QCPAxis::atBottom)
16406 {
16110 {
16407 point.setX(lowerKey);
16111 point.setX(lowerKey);
16408 if ((valueAxis->range().upper < 0 && !valueAxis->rangeReversed()) ||
16112 if ((valueAxis->range().upper < 0 && !valueAxis->rangeReversed()) ||
16409 (valueAxis->range().upper > 0 && valueAxis->rangeReversed())) // if range is negative, zero is on opposite side of key axis
16113 (valueAxis->range().upper > 0 && valueAxis->rangeReversed())) // if range is negative, zero is on opposite side of key axis
16410 point.setY(keyAxis->axisRect()->top());
16114 point.setY(keyAxis->axisRect()->top());
16411 else
16115 else
16412 point.setY(keyAxis->axisRect()->bottom());
16116 point.setY(keyAxis->axisRect()->bottom());
16413 }
16117 }
16414 }
16118 }
16415 return point;
16119 return point;
16416 }
16120 }
16417
16121
16418 /*! \internal
16122 /*! \internal
@@ -16431,53 +16135,53 QPointF QCPGraph::lowerFillBasePoint(dou
16431 */
16135 */
16432 QPointF QCPGraph::upperFillBasePoint(double upperKey) const
16136 QPointF QCPGraph::upperFillBasePoint(double upperKey) const
16433 {
16137 {
16434 QCPAxis *keyAxis = mKeyAxis.data();
16138 QCPAxis *keyAxis = mKeyAxis.data();
16435 QCPAxis *valueAxis = mValueAxis.data();
16139 QCPAxis *valueAxis = mValueAxis.data();
16436 if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return QPointF(); }
16140 if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return QPointF(); }
16437
16141
16438 QPointF point;
16142 QPointF point;
16439 if (valueAxis->scaleType() == QCPAxis::stLinear)
16143 if (valueAxis->scaleType() == QCPAxis::stLinear)
16440 {
16144 {
16441 if (keyAxis->axisType() == QCPAxis::atLeft)
16145 if (keyAxis->axisType() == QCPAxis::atLeft)
16442 {
16146 {
16443 point.setX(valueAxis->coordToPixel(0));
16147 point.setX(valueAxis->coordToPixel(0));
16444 point.setY(upperKey);
16148 point.setY(upperKey);
16445 } else if (keyAxis->axisType() == QCPAxis::atRight)
16149 } else if (keyAxis->axisType() == QCPAxis::atRight)
16446 {
16150 {
16447 point.setX(valueAxis->coordToPixel(0));
16151 point.setX(valueAxis->coordToPixel(0));
16448 point.setY(upperKey);
16152 point.setY(upperKey);
16449 } else if (keyAxis->axisType() == QCPAxis::atTop)
16153 } else if (keyAxis->axisType() == QCPAxis::atTop)
16450 {
16154 {
16451 point.setX(upperKey);
16155 point.setX(upperKey);
16452 point.setY(valueAxis->coordToPixel(0));
16156 point.setY(valueAxis->coordToPixel(0));
16453 } else if (keyAxis->axisType() == QCPAxis::atBottom)
16157 } else if (keyAxis->axisType() == QCPAxis::atBottom)
16454 {
16158 {
16455 point.setX(upperKey);
16159 point.setX(upperKey);
16456 point.setY(valueAxis->coordToPixel(0));
16160 point.setY(valueAxis->coordToPixel(0));
16457 }
16161 }
16458 } else // valueAxis->mScaleType == QCPAxis::stLogarithmic
16162 } else // valueAxis->mScaleType == QCPAxis::stLogarithmic
16459 {
16163 {
16460 // In logarithmic scaling we can't just draw to value 0 so we just fill all the way
16164 // In logarithmic scaling we can't just draw to value 0 so we just fill all the way
16461 // to the axis which is in the direction towards 0
16165 // to the axis which is in the direction towards 0
16462 if (keyAxis->orientation() == Qt::Vertical)
16166 if (keyAxis->orientation() == Qt::Vertical)
16463 {
16167 {
16464 if ((valueAxis->range().upper < 0 && !valueAxis->rangeReversed()) ||
16168 if ((valueAxis->range().upper < 0 && !valueAxis->rangeReversed()) ||
16465 (valueAxis->range().upper > 0 && valueAxis->rangeReversed())) // if range is negative, zero is on opposite side of key axis
16169 (valueAxis->range().upper > 0 && valueAxis->rangeReversed())) // if range is negative, zero is on opposite side of key axis
16466 point.setX(keyAxis->axisRect()->right());
16170 point.setX(keyAxis->axisRect()->right());
16467 else
16171 else
16468 point.setX(keyAxis->axisRect()->left());
16172 point.setX(keyAxis->axisRect()->left());
16469 point.setY(upperKey);
16173 point.setY(upperKey);
16470 } else if (keyAxis->axisType() == QCPAxis::atTop || keyAxis->axisType() == QCPAxis::atBottom)
16174 } else if (keyAxis->axisType() == QCPAxis::atTop || keyAxis->axisType() == QCPAxis::atBottom)
16471 {
16175 {
16472 point.setX(upperKey);
16176 point.setX(upperKey);
16473 if ((valueAxis->range().upper < 0 && !valueAxis->rangeReversed()) ||
16177 if ((valueAxis->range().upper < 0 && !valueAxis->rangeReversed()) ||
16474 (valueAxis->range().upper > 0 && valueAxis->rangeReversed())) // if range is negative, zero is on opposite side of key axis
16178 (valueAxis->range().upper > 0 && valueAxis->rangeReversed())) // if range is negative, zero is on opposite side of key axis
16475 point.setY(keyAxis->axisRect()->top());
16179 point.setY(keyAxis->axisRect()->top());
16476 else
16180 else
16477 point.setY(keyAxis->axisRect()->bottom());
16181 point.setY(keyAxis->axisRect()->bottom());
16478 }
16182 }
16479 }
16183 }
16480 return point;
16184 return point;
16481 }
16185 }
16482
16186
16483 /*! \internal
16187 /*! \internal
@@ -16491,137 +16195,137 QPointF QCPGraph::upperFillBasePoint(dou
16491 */
16195 */
16492 const QPolygonF QCPGraph::getChannelFillPolygon(const QVector<QPointF> *lineData) const
16196 const QPolygonF QCPGraph::getChannelFillPolygon(const QVector<QPointF> *lineData) const
16493 {
16197 {
16494 if (!mChannelFillGraph)
16198 if (!mChannelFillGraph)
16495 return QPolygonF();
16199 return QPolygonF();
16496
16200
16497 QCPAxis *keyAxis = mKeyAxis.data();
16201 QCPAxis *keyAxis = mKeyAxis.data();
16498 QCPAxis *valueAxis = mValueAxis.data();
16202 QCPAxis *valueAxis = mValueAxis.data();
16499 if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return QPolygonF(); }
16203 if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return QPolygonF(); }
16500 if (!mChannelFillGraph.data()->mKeyAxis) { qDebug() << Q_FUNC_INFO << "channel fill target key axis invalid"; return QPolygonF(); }
16204 if (!mChannelFillGraph.data()->mKeyAxis) { qDebug() << Q_FUNC_INFO << "channel fill target key axis invalid"; return QPolygonF(); }
16501
16205
16502 if (mChannelFillGraph.data()->mKeyAxis.data()->orientation() != keyAxis->orientation())
16206 if (mChannelFillGraph.data()->mKeyAxis.data()->orientation() != keyAxis->orientation())
16503 return QPolygonF(); // don't have same axis orientation, can't fill that (Note: if keyAxis fits, valueAxis will fit too, because it's always orthogonal to keyAxis)
16207 return QPolygonF(); // don't have same axis orientation, can't fill that (Note: if keyAxis fits, valueAxis will fit too, because it's always orthogonal to keyAxis)
16504
16208
16505 if (lineData->isEmpty()) return QPolygonF();
16209 if (lineData->isEmpty()) return QPolygonF();
16506 QVector<QPointF> otherData;
16210 QVector<QPointF> otherData;
16507 mChannelFillGraph.data()->getPlotData(&otherData, 0);
16211 mChannelFillGraph.data()->getPlotData(&otherData, 0);
16508 if (otherData.isEmpty()) return QPolygonF();
16212 if (otherData.isEmpty()) return QPolygonF();
16509 QVector<QPointF> thisData;
16213 QVector<QPointF> thisData;
16510 thisData.reserve(lineData->size()+otherData.size()); // because we will join both vectors at end of this function
16214 thisData.reserve(lineData->size()+otherData.size()); // because we will join both vectors at end of this function
16511 for (int i=0; i<lineData->size(); ++i) // don't use the vector<<(vector), it squeezes internally, which ruins the performance tuning with reserve()
16215 for (int i=0; i<lineData->size(); ++i) // don't use the vector<<(vector), it squeezes internally, which ruins the performance tuning with reserve()
16512 thisData << lineData->at(i);
16216 thisData << lineData->at(i);
16513
16217
16514 // pointers to be able to swap them, depending which data range needs cropping:
16218 // pointers to be able to swap them, depending which data range needs cropping:
16515 QVector<QPointF> *staticData = &thisData;
16219 QVector<QPointF> *staticData = &thisData;
16516 QVector<QPointF> *croppedData = &otherData;
16220 QVector<QPointF> *croppedData = &otherData;
16517
16221
16518 // crop both vectors to ranges in which the keys overlap (which coord is key, depends on axisType):
16222 // crop both vectors to ranges in which the keys overlap (which coord is key, depends on axisType):
16519 if (keyAxis->orientation() == Qt::Horizontal)
16223 if (keyAxis->orientation() == Qt::Horizontal)
16520 {
16224 {
16521 // x is key
16225 // x is key
16522 // if an axis range is reversed, the data point keys will be descending. Reverse them, since following algorithm assumes ascending keys:
16226 // if an axis range is reversed, the data point keys will be descending. Reverse them, since following algorithm assumes ascending keys:
16523 if (staticData->first().x() > staticData->last().x())
16227 if (staticData->first().x() > staticData->last().x())
16524 {
16228 {
16525 int size = staticData->size();
16229 int size = staticData->size();
16526 for (int i=0; i<size/2; ++i)
16230 for (int i=0; i<size/2; ++i)
16527 qSwap((*staticData)[i], (*staticData)[size-1-i]);
16231 qSwap((*staticData)[i], (*staticData)[size-1-i]);
16528 }
16232 }
16529 if (croppedData->first().x() > croppedData->last().x())
16233 if (croppedData->first().x() > croppedData->last().x())
16530 {
16234 {
16531 int size = croppedData->size();
16235 int size = croppedData->size();
16532 for (int i=0; i<size/2; ++i)
16236 for (int i=0; i<size/2; ++i)
16533 qSwap((*croppedData)[i], (*croppedData)[size-1-i]);
16237 qSwap((*croppedData)[i], (*croppedData)[size-1-i]);
16534 }
16238 }
16535 // crop lower bound:
16239 // crop lower bound:
16536 if (staticData->first().x() < croppedData->first().x()) // other one must be cropped
16240 if (staticData->first().x() < croppedData->first().x()) // other one must be cropped
16537 qSwap(staticData, croppedData);
16241 qSwap(staticData, croppedData);
16538 int lowBound = findIndexBelowX(croppedData, staticData->first().x());
16242 int lowBound = findIndexBelowX(croppedData, staticData->first().x());
16539 if (lowBound == -1) return QPolygonF(); // key ranges have no overlap
16243 if (lowBound == -1) return QPolygonF(); // key ranges have no overlap
16540 croppedData->remove(0, lowBound);
16244 croppedData->remove(0, lowBound);
16541 // set lowest point of cropped data to fit exactly key position of first static data
16245 // set lowest point of cropped data to fit exactly key position of first static data
16542 // point via linear interpolation:
16246 // point via linear interpolation:
16543 if (croppedData->size() < 2) return QPolygonF(); // need at least two points for interpolation
16247 if (croppedData->size() < 2) return QPolygonF(); // need at least two points for interpolation
16544 double slope;
16248 double slope;
16545 if (croppedData->at(1).x()-croppedData->at(0).x() != 0)
16249 if (croppedData->at(1).x()-croppedData->at(0).x() != 0)
16546 slope = (croppedData->at(1).y()-croppedData->at(0).y())/(croppedData->at(1).x()-croppedData->at(0).x());
16250 slope = (croppedData->at(1).y()-croppedData->at(0).y())/(croppedData->at(1).x()-croppedData->at(0).x());
16547 else
16251 else
16548 slope = 0;
16252 slope = 0;
16549 (*croppedData)[0].setY(croppedData->at(0).y()+slope*(staticData->first().x()-croppedData->at(0).x()));
16253 (*croppedData)[0].setY(croppedData->at(0).y()+slope*(staticData->first().x()-croppedData->at(0).x()));
16550 (*croppedData)[0].setX(staticData->first().x());
16254 (*croppedData)[0].setX(staticData->first().x());
16551
16255
16552 // crop upper bound:
16256 // crop upper bound:
16553 if (staticData->last().x() > croppedData->last().x()) // other one must be cropped
16257 if (staticData->last().x() > croppedData->last().x()) // other one must be cropped
16554 qSwap(staticData, croppedData);
16258 qSwap(staticData, croppedData);
16555 int highBound = findIndexAboveX(croppedData, staticData->last().x());
16259 int highBound = findIndexAboveX(croppedData, staticData->last().x());
16556 if (highBound == -1) return QPolygonF(); // key ranges have no overlap
16260 if (highBound == -1) return QPolygonF(); // key ranges have no overlap
16557 croppedData->remove(highBound+1, croppedData->size()-(highBound+1));
16261 croppedData->remove(highBound+1, croppedData->size()-(highBound+1));
16558 // set highest point of cropped data to fit exactly key position of last static data
16262 // set highest point of cropped data to fit exactly key position of last static data
16559 // point via linear interpolation:
16263 // point via linear interpolation:
16560 if (croppedData->size() < 2) return QPolygonF(); // need at least two points for interpolation
16264 if (croppedData->size() < 2) return QPolygonF(); // need at least two points for interpolation
16561 int li = croppedData->size()-1; // last index
16265 int li = croppedData->size()-1; // last index
16562 if (croppedData->at(li).x()-croppedData->at(li-1).x() != 0)
16266 if (croppedData->at(li).x()-croppedData->at(li-1).x() != 0)
16563 slope = (croppedData->at(li).y()-croppedData->at(li-1).y())/(croppedData->at(li).x()-croppedData->at(li-1).x());
16267 slope = (croppedData->at(li).y()-croppedData->at(li-1).y())/(croppedData->at(li).x()-croppedData->at(li-1).x());
16564 else
16268 else
16565 slope = 0;
16269 slope = 0;
16566 (*croppedData)[li].setY(croppedData->at(li-1).y()+slope*(staticData->last().x()-croppedData->at(li-1).x()));
16270 (*croppedData)[li].setY(croppedData->at(li-1).y()+slope*(staticData->last().x()-croppedData->at(li-1).x()));
16567 (*croppedData)[li].setX(staticData->last().x());
16271 (*croppedData)[li].setX(staticData->last().x());
16568 } else // mKeyAxis->orientation() == Qt::Vertical
16272 } else // mKeyAxis->orientation() == Qt::Vertical
16569 {
16273 {
16570 // y is key
16274 // y is key
16571 // similar to "x is key" but switched x,y. Further, lower/upper meaning is inverted compared to x,
16275 // similar to "x is key" but switched x,y. Further, lower/upper meaning is inverted compared to x,
16572 // because in pixel coordinates, y increases from top to bottom, not bottom to top like data coordinate.
16276 // because in pixel coordinates, y increases from top to bottom, not bottom to top like data coordinate.
16573 // if an axis range is reversed, the data point keys will be descending. Reverse them, since following algorithm assumes ascending keys:
16277 // if an axis range is reversed, the data point keys will be descending. Reverse them, since following algorithm assumes ascending keys:
16574 if (staticData->first().y() < staticData->last().y())
16278 if (staticData->first().y() < staticData->last().y())
16575 {
16279 {
16576 int size = staticData->size();
16280 int size = staticData->size();
16577 for (int i=0; i<size/2; ++i)
16281 for (int i=0; i<size/2; ++i)
16578 qSwap((*staticData)[i], (*staticData)[size-1-i]);
16282 qSwap((*staticData)[i], (*staticData)[size-1-i]);
16579 }
16283 }
16580 if (croppedData->first().y() < croppedData->last().y())
16284 if (croppedData->first().y() < croppedData->last().y())
16581 {
16285 {
16582 int size = croppedData->size();
16286 int size = croppedData->size();
16583 for (int i=0; i<size/2; ++i)
16287 for (int i=0; i<size/2; ++i)
16584 qSwap((*croppedData)[i], (*croppedData)[size-1-i]);
16288 qSwap((*croppedData)[i], (*croppedData)[size-1-i]);
16585 }
16289 }
16586 // crop lower bound:
16290 // crop lower bound:
16587 if (staticData->first().y() > croppedData->first().y()) // other one must be cropped
16291 if (staticData->first().y() > croppedData->first().y()) // other one must be cropped
16588 qSwap(staticData, croppedData);
16292 qSwap(staticData, croppedData);
16589 int lowBound = findIndexAboveY(croppedData, staticData->first().y());
16293 int lowBound = findIndexAboveY(croppedData, staticData->first().y());
16590 if (lowBound == -1) return QPolygonF(); // key ranges have no overlap
16294 if (lowBound == -1) return QPolygonF(); // key ranges have no overlap
16591 croppedData->remove(0, lowBound);
16295 croppedData->remove(0, lowBound);
16592 // set lowest point of cropped data to fit exactly key position of first static data
16296 // set lowest point of cropped data to fit exactly key position of first static data
16593 // point via linear interpolation:
16297 // point via linear interpolation:
16594 if (croppedData->size() < 2) return QPolygonF(); // need at least two points for interpolation
16298 if (croppedData->size() < 2) return QPolygonF(); // need at least two points for interpolation
16595 double slope;
16299 double slope;
16596 if (croppedData->at(1).y()-croppedData->at(0).y() != 0) // avoid division by zero in step plots
16300 if (croppedData->at(1).y()-croppedData->at(0).y() != 0) // avoid division by zero in step plots
16597 slope = (croppedData->at(1).x()-croppedData->at(0).x())/(croppedData->at(1).y()-croppedData->at(0).y());
16301 slope = (croppedData->at(1).x()-croppedData->at(0).x())/(croppedData->at(1).y()-croppedData->at(0).y());
16598 else
16302 else
16599 slope = 0;
16303 slope = 0;
16600 (*croppedData)[0].setX(croppedData->at(0).x()+slope*(staticData->first().y()-croppedData->at(0).y()));
16304 (*croppedData)[0].setX(croppedData->at(0).x()+slope*(staticData->first().y()-croppedData->at(0).y()));
16601 (*croppedData)[0].setY(staticData->first().y());
16305 (*croppedData)[0].setY(staticData->first().y());
16602
16306
16603 // crop upper bound:
16307 // crop upper bound:
16604 if (staticData->last().y() < croppedData->last().y()) // other one must be cropped
16308 if (staticData->last().y() < croppedData->last().y()) // other one must be cropped
16605 qSwap(staticData, croppedData);
16309 qSwap(staticData, croppedData);
16606 int highBound = findIndexBelowY(croppedData, staticData->last().y());
16310 int highBound = findIndexBelowY(croppedData, staticData->last().y());
16607 if (highBound == -1) return QPolygonF(); // key ranges have no overlap
16311 if (highBound == -1) return QPolygonF(); // key ranges have no overlap
16608 croppedData->remove(highBound+1, croppedData->size()-(highBound+1));
16312 croppedData->remove(highBound+1, croppedData->size()-(highBound+1));
16609 // set highest point of cropped data to fit exactly key position of last static data
16313 // set highest point of cropped data to fit exactly key position of last static data
16610 // point via linear interpolation:
16314 // point via linear interpolation:
16611 if (croppedData->size() < 2) return QPolygonF(); // need at least two points for interpolation
16315 if (croppedData->size() < 2) return QPolygonF(); // need at least two points for interpolation
16612 int li = croppedData->size()-1; // last index
16316 int li = croppedData->size()-1; // last index
16613 if (croppedData->at(li).y()-croppedData->at(li-1).y() != 0) // avoid division by zero in step plots
16317 if (croppedData->at(li).y()-croppedData->at(li-1).y() != 0) // avoid division by zero in step plots
16614 slope = (croppedData->at(li).x()-croppedData->at(li-1).x())/(croppedData->at(li).y()-croppedData->at(li-1).y());
16318 slope = (croppedData->at(li).x()-croppedData->at(li-1).x())/(croppedData->at(li).y()-croppedData->at(li-1).y());
16615 else
16319 else
16616 slope = 0;
16320 slope = 0;
16617 (*croppedData)[li].setX(croppedData->at(li-1).x()+slope*(staticData->last().y()-croppedData->at(li-1).y()));
16321 (*croppedData)[li].setX(croppedData->at(li-1).x()+slope*(staticData->last().y()-croppedData->at(li-1).y()));
16618 (*croppedData)[li].setY(staticData->last().y());
16322 (*croppedData)[li].setY(staticData->last().y());
16619 }
16323 }
16620
16324
16621 // return joined:
16325 // return joined:
16622 for (int i=otherData.size()-1; i>=0; --i) // insert reversed, otherwise the polygon will be twisted
16326 for (int i=otherData.size()-1; i>=0; --i) // insert reversed, otherwise the polygon will be twisted
16623 thisData << otherData.at(i);
16327 thisData << otherData.at(i);
16624 return QPolygonF(thisData);
16328 return QPolygonF(thisData);
16625 }
16329 }
16626
16330
16627 /*! \internal
16331 /*! \internal
@@ -16633,17 +16337,17 const QPolygonF QCPGraph::getChannelFill
16633 */
16337 */
16634 int QCPGraph::findIndexAboveX(const QVector<QPointF> *data, double x) const
16338 int QCPGraph::findIndexAboveX(const QVector<QPointF> *data, double x) const
16635 {
16339 {
16636 for (int i=data->size()-1; i>=0; --i)
16340 for (int i=data->size()-1; i>=0; --i)
16637 {
16341 {
16638 if (data->at(i).x() < x)
16342 if (data->at(i).x() < x)
16639 {
16343 {
16640 if (i<data->size()-1)
16344 if (i<data->size()-1)
16641 return i+1;
16345 return i+1;
16642 else
16346 else
16643 return data->size()-1;
16347 return data->size()-1;
16644 }
16348 }
16645 }
16349 }
16646 return -1;
16350 return -1;
16647 }
16351 }
16648
16352
16649 /*! \internal
16353 /*! \internal
@@ -16655,17 +16359,17 int QCPGraph::findIndexAboveX(const QVec
16655 */
16359 */
16656 int QCPGraph::findIndexBelowX(const QVector<QPointF> *data, double x) const
16360 int QCPGraph::findIndexBelowX(const QVector<QPointF> *data, double x) const
16657 {
16361 {
16658 for (int i=0; i<data->size(); ++i)
16362 for (int i=0; i<data->size(); ++i)
16659 {
16363 {
16660 if (data->at(i).x() > x)
16364 if (data->at(i).x() > x)
16661 {
16365 {
16662 if (i>0)
16366 if (i>0)
16663 return i-1;
16367 return i-1;
16664 else
16368 else
16665 return 0;
16369 return 0;
16666 }
16370 }
16667 }
16371 }
16668 return -1;
16372 return -1;
16669 }
16373 }
16670
16374
16671 /*! \internal
16375 /*! \internal
@@ -16677,17 +16381,17 int QCPGraph::findIndexBelowX(const QVec
16677 */
16381 */
16678 int QCPGraph::findIndexAboveY(const QVector<QPointF> *data, double y) const
16382 int QCPGraph::findIndexAboveY(const QVector<QPointF> *data, double y) const
16679 {
16383 {
16680 for (int i=0; i<data->size(); ++i)
16384 for (int i=0; i<data->size(); ++i)
16681 {
16385 {
16682 if (data->at(i).y() < y)
16386 if (data->at(i).y() < y)
16683 {
16387 {
16684 if (i>0)
16388 if (i>0)
16685 return i-1;
16389 return i-1;
16686 else
16390 else
16687 return 0;
16391 return 0;
16688 }
16392 }
16689 }
16393 }
16690 return -1;
16394 return -1;
16691 }
16395 }
16692
16396
16693 /*! \internal
16397 /*! \internal
@@ -16702,66 +16406,66 int QCPGraph::findIndexAboveY(const QVec
16702 */
16406 */
16703 double QCPGraph::pointDistance(const QPointF &pixelPoint) const
16407 double QCPGraph::pointDistance(const QPointF &pixelPoint) const
16704 {
16408 {
16705 if (mData->isEmpty())
16409 if (mData->isEmpty())
16706 {
16410 {
16707 qDebug() << Q_FUNC_INFO << "requested point distance on graph" << mName << "without data";
16411 qDebug() << Q_FUNC_INFO << "requested point distance on graph" << mName << "without data";
16708 return 500;
16412 return 500;
16709 }
16413 }
16710 if (mData->size() == 1)
16414 if (mData->size() == 1)
16711 {
16415 {
16712 QPointF dataPoint = coordsToPixels(mData->constBegin().key(), mData->constBegin().value().value);
16416 QPointF dataPoint = coordsToPixels(mData->constBegin().key(), mData->constBegin().value().value);
16713 return QVector2D(dataPoint-pixelPoint).length();
16417 return QVector2D(dataPoint-pixelPoint).length();
16714 }
16418 }
16715
16419
16716 if (mLineStyle == lsNone && mScatterStyle.isNone())
16420 if (mLineStyle == lsNone && mScatterStyle.isNone())
16717 return 500;
16421 return 500;
16718
16422
16719 // calculate minimum distances to graph representation:
16423 // calculate minimum distances to graph representation:
16720 if (mLineStyle == lsNone)
16424 if (mLineStyle == lsNone)
16721 {
16425 {
16722 // no line displayed, only calculate distance to scatter points:
16426 // no line displayed, only calculate distance to scatter points:
16723 QVector<QCPData> *scatterData = new QVector<QCPData>;
16427 QVector<QCPData> *scatterData = new QVector<QCPData>;
16724 getScatterPlotData(scatterData);
16428 getScatterPlotData(scatterData);
16725 double minDistSqr = std::numeric_limits<double>::max();
16429 double minDistSqr = std::numeric_limits<double>::max();
16726 QPointF ptA;
16430 QPointF ptA;
16727 QPointF ptB = coordsToPixels(scatterData->at(0).key, scatterData->at(0).value); // getScatterPlotData returns in plot coordinates, so transform to pixels
16431 QPointF ptB = coordsToPixels(scatterData->at(0).key, scatterData->at(0).value); // getScatterPlotData returns in plot coordinates, so transform to pixels
16728 for (int i=1; i<scatterData->size(); ++i)
16432 for (int i=1; i<scatterData->size(); ++i)
16729 {
16433 {
16730 ptA = ptB;
16434 ptA = ptB;
16731 ptB = coordsToPixels(scatterData->at(i).key, scatterData->at(i).value);
16435 ptB = coordsToPixels(scatterData->at(i).key, scatterData->at(i).value);
16732 double currentDistSqr = distSqrToLine(ptA, ptB, pixelPoint);
16436 double currentDistSqr = distSqrToLine(ptA, ptB, pixelPoint);
16733 if (currentDistSqr < minDistSqr)
16437 if (currentDistSqr < minDistSqr)
16734 minDistSqr = currentDistSqr;
16735 }
16736 delete scatterData;
16737 return qSqrt(minDistSqr);
16738 } else
16739 {
16740 // line displayed calculate distance to line segments:
16741 QVector<QPointF> *lineData = new QVector<QPointF>;
16742 getPlotData(lineData, 0); // unlike with getScatterPlotData we get pixel coordinates here
16743 double minDistSqr = std::numeric_limits<double>::max();
16744 if (mLineStyle == lsImpulse)
16745 {
16746 // impulse plot differs from other line styles in that the lineData points are only pairwise connected:
16747 for (int i=0; i<lineData->size()-1; i+=2) // iterate pairs
16748 {
16749 double currentDistSqr = distSqrToLine(lineData->at(i), lineData->at(i+1), pixelPoint);
16750 if (currentDistSqr < minDistSqr)
16751 minDistSqr = currentDistSqr;
16438 minDistSqr = currentDistSqr;
16439 }
16440 delete scatterData;
16441 return qSqrt(minDistSqr);
16442 } else
16443 {
16444 // line displayed calculate distance to line segments:
16445 QVector<QPointF> *lineData = new QVector<QPointF>;
16446 getPlotData(lineData, 0); // unlike with getScatterPlotData we get pixel coordinates here
16447 double minDistSqr = std::numeric_limits<double>::max();
16448 if (mLineStyle == lsImpulse)
16449 {
16450 // impulse plot differs from other line styles in that the lineData points are only pairwise connected:
16451 for (int i=0; i<lineData->size()-1; i+=2) // iterate pairs
16452 {
16453 double currentDistSqr = distSqrToLine(lineData->at(i), lineData->at(i+1), pixelPoint);
16454 if (currentDistSqr < minDistSqr)
16455 minDistSqr = currentDistSqr;
16752 }
16456 }
16753 } else
16457 } else
16754 {
16458 {
16755 // all other line plots (line and step) connect points directly:
16459 // all other line plots (line and step) connect points directly:
16756 for (int i=0; i<lineData->size()-1; ++i)
16460 for (int i=0; i<lineData->size()-1; ++i)
16757 {
16461 {
16758 double currentDistSqr = distSqrToLine(lineData->at(i), lineData->at(i+1), pixelPoint);
16462 double currentDistSqr = distSqrToLine(lineData->at(i), lineData->at(i+1), pixelPoint);
16759 if (currentDistSqr < minDistSqr)
16463 if (currentDistSqr < minDistSqr)
16760 minDistSqr = currentDistSqr;
16464 minDistSqr = currentDistSqr;
16761 }
16465 }
16762 }
16466 }
16763 delete lineData;
16467 delete lineData;
16764 return qSqrt(minDistSqr);
16468 return qSqrt(minDistSqr);
16765 }
16469 }
16766 }
16470 }
16767
16471
@@ -16775,37 +16479,33 double QCPGraph::pointDistance(const QPo
16775 */
16479 */
16776 int QCPGraph::findIndexBelowY(const QVector<QPointF> *data, double y) const
16480 int QCPGraph::findIndexBelowY(const QVector<QPointF> *data, double y) const
16777 {
16481 {
16778 for (int i=data->size()-1; i>=0; --i)
16482 for (int i=data->size()-1; i>=0; --i)
16779 {
16483 {
16780 if (data->at(i).y() > y)
16484 if (data->at(i).y() > y)
16781 {
16485 {
16782 if (i<data->size()-1)
16486 if (i<data->size()-1)
16783 return i+1;
16487 return i+1;
16784 else
16488 else
16785 return data->size()-1;
16489 return data->size()-1;
16786 }
16490 }
16787 }
16491 }
16788 return -1;
16492 return -1;
16789 }
16493 }
16790
16494
16791 /* inherits documentation from base class */
16495 /* inherits documentation from base class */
16792 QCPRange QCPGraph::getKeyRange(bool &foundRange, SignDomain inSignDomain) const
16496 QCPRange QCPGraph::getKeyRange(bool &foundRange, SignDomain inSignDomain) const
16793 {
16497 {
16794 // just call the specialized version which takes an additional argument whether error bars
16498 // just call the specialized version which takes an additional argument whether error bars
16795 // should also be taken into consideration for range calculation. We set this to true here.
16499 // should also be taken into consideration for range calculation. We set this to true here.
16796 if(mUseFastVectors)
16500 return getKeyRange(foundRange, inSignDomain, true);
16797 return getKeyRangeVector(foundRange, inSignDomain, true);
16798 return getKeyRange(foundRange, inSignDomain, true);
16799 }
16501 }
16800
16502
16801 /* inherits documentation from base class */
16503 /* inherits documentation from base class */
16802 QCPRange QCPGraph::getValueRange(bool &foundRange, SignDomain inSignDomain) const
16504 QCPRange QCPGraph::getValueRange(bool &foundRange, SignDomain inSignDomain) const
16803 {
16505 {
16804 // just call the specialized version which takes an additional argument whether error bars
16506 // just call the specialized version which takes an additional argument whether error bars
16805 // should also be taken into consideration for range calculation. We set this to true here.
16507 // should also be taken into consideration for range calculation. We set this to true here.
16806 if(mUseFastVectors)
16508 return getValueRange(foundRange, inSignDomain, true);
16807 return getValueRangeVector(foundRange, inSignDomain, true);
16808 return getValueRange(foundRange, inSignDomain, true);
16809 }
16509 }
16810
16510
16811 /*! \overload
16511 /*! \overload
@@ -16816,202 +16516,102 QCPRange QCPGraph::getValueRange(bool &f
16816 */
16516 */
16817 QCPRange QCPGraph::getKeyRange(bool &foundRange, SignDomain inSignDomain, bool includeErrors) const
16517 QCPRange QCPGraph::getKeyRange(bool &foundRange, SignDomain inSignDomain, bool includeErrors) const
16818 {
16518 {
16819 QCPRange range;
16519 QCPRange range;
16820 bool haveLower = false;
16520 bool haveLower = false;
16821 bool haveUpper = false;
16521 bool haveUpper = false;
16822
16522
16823 double current, currentErrorMinus, currentErrorPlus;
16523 double current, currentErrorMinus, currentErrorPlus;
16824
16524
16825 if (inSignDomain == sdBoth) // range may be anywhere
16525 if (inSignDomain == sdBoth) // range may be anywhere
16826 {
16526 {
16827 QCPDataMap::const_iterator it = mData->constBegin();
16527 QCPDataMap::const_iterator it = mData->constBegin();
16828 while (it != mData->constEnd())
16528 while (it != mData->constEnd())
16829 {
16529 {
16830 current = it.value().key;
16530 current = it.value().key;
16831 currentErrorMinus = (includeErrors ? it.value().keyErrorMinus : 0);
16531 currentErrorMinus = (includeErrors ? it.value().keyErrorMinus : 0);
16832 currentErrorPlus = (includeErrors ? it.value().keyErrorPlus : 0);
16532 currentErrorPlus = (includeErrors ? it.value().keyErrorPlus : 0);
16833 if (current-currentErrorMinus < range.lower || !haveLower)
16533 if (current-currentErrorMinus < range.lower || !haveLower)
16834 {
16534 {
16835 range.lower = current-currentErrorMinus;
16535 range.lower = current-currentErrorMinus;
16836 haveLower = true;
16536 haveLower = true;
16837 }
16537 }
16838 if (current+currentErrorPlus > range.upper || !haveUpper)
16538 if (current+currentErrorPlus > range.upper || !haveUpper)
16839 {
16539 {
16840 range.upper = current+currentErrorPlus;
16540 range.upper = current+currentErrorPlus;
16841 haveUpper = true;
16541 haveUpper = true;
16842 }
16542 }
16843 ++it;
16543 ++it;
16844 }
16544 }
16845 } else if (inSignDomain == sdNegative) // range may only be in the negative sign domain
16545 } else if (inSignDomain == sdNegative) // range may only be in the negative sign domain
16846 {
16546 {
16847 QCPDataMap::const_iterator it = mData->constBegin();
16547 QCPDataMap::const_iterator it = mData->constBegin();
16848 while (it != mData->constEnd())
16548 while (it != mData->constEnd())
16849 {
16549 {
16850 current = it.value().key;
16550 current = it.value().key;
16851 currentErrorMinus = (includeErrors ? it.value().keyErrorMinus : 0);
16551 currentErrorMinus = (includeErrors ? it.value().keyErrorMinus : 0);
16852 currentErrorPlus = (includeErrors ? it.value().keyErrorPlus : 0);
16552 currentErrorPlus = (includeErrors ? it.value().keyErrorPlus : 0);
16853 if ((current-currentErrorMinus < range.lower || !haveLower) && current-currentErrorMinus < 0)
16553 if ((current-currentErrorMinus < range.lower || !haveLower) && current-currentErrorMinus < 0)
16854 {
16554 {
16855 range.lower = current-currentErrorMinus;
16555 range.lower = current-currentErrorMinus;
16856 haveLower = true;
16556 haveLower = true;
16857 }
16557 }
16858 if ((current+currentErrorPlus > range.upper || !haveUpper) && current+currentErrorPlus < 0)
16558 if ((current+currentErrorPlus > range.upper || !haveUpper) && current+currentErrorPlus < 0)
16859 {
16559 {
16860 range.upper = current+currentErrorPlus;
16560 range.upper = current+currentErrorPlus;
16861 haveUpper = true;
16561 haveUpper = true;
16862 }
16562 }
16863 if (includeErrors) // in case point is in valid sign domain but errobars stretch beyond it, we still want to geht that point.
16563 if (includeErrors) // in case point is in valid sign domain but errobars stretch beyond it, we still want to geht that point.
16864 {
16564 {
16865 if ((current < range.lower || !haveLower) && current < 0)
16565 if ((current < range.lower || !haveLower) && current < 0)
16866 {
16566 {
16867 range.lower = current;
16567 range.lower = current;
16868 haveLower = true;
16568 haveLower = true;
16869 }
16569 }
16870 if ((current > range.upper || !haveUpper) && current < 0)
16570 if ((current > range.upper || !haveUpper) && current < 0)
16871 {
16571 {
16872 range.upper = current;
16572 range.upper = current;
16873 haveUpper = true;
16573 haveUpper = true;
16874 }
16574 }
16875 }
16575 }
16876 ++it;
16576 ++it;
16877 }
16577 }
16878 } else if (inSignDomain == sdPositive) // range may only be in the positive sign domain
16578 } else if (inSignDomain == sdPositive) // range may only be in the positive sign domain
16879 {
16579 {
16880 QCPDataMap::const_iterator it = mData->constBegin();
16580 QCPDataMap::const_iterator it = mData->constBegin();
16881 while (it != mData->constEnd())
16581 while (it != mData->constEnd())
16882 {
16582 {
16883 current = it.value().key;
16583 current = it.value().key;
16884 currentErrorMinus = (includeErrors ? it.value().keyErrorMinus : 0);
16584 currentErrorMinus = (includeErrors ? it.value().keyErrorMinus : 0);
16885 currentErrorPlus = (includeErrors ? it.value().keyErrorPlus : 0);
16585 currentErrorPlus = (includeErrors ? it.value().keyErrorPlus : 0);
16886 if ((current-currentErrorMinus < range.lower || !haveLower) && current-currentErrorMinus > 0)
16586 if ((current-currentErrorMinus < range.lower || !haveLower) && current-currentErrorMinus > 0)
16887 {
16587 {
16888 range.lower = current-currentErrorMinus;
16588 range.lower = current-currentErrorMinus;
16889 haveLower = true;
16589 haveLower = true;
16890 }
16590 }
16891 if ((current+currentErrorPlus > range.upper || !haveUpper) && current+currentErrorPlus > 0)
16591 if ((current+currentErrorPlus > range.upper || !haveUpper) && current+currentErrorPlus > 0)
16892 {
16592 {
16893 range.upper = current+currentErrorPlus;
16593 range.upper = current+currentErrorPlus;
16894 haveUpper = true;
16594 haveUpper = true;
16895 }
16595 }
16896 if (includeErrors) // in case point is in valid sign domain but errobars stretch beyond it, we still want to get that point.
16596 if (includeErrors) // in case point is in valid sign domain but errobars stretch beyond it, we still want to get that point.
16897 {
16597 {
16898 if ((current < range.lower || !haveLower) && current > 0)
16598 if ((current < range.lower || !haveLower) && current > 0)
16899 {
16599 {
16900 range.lower = current;
16600 range.lower = current;
16901 haveLower = true;
16601 haveLower = true;
16902 }
16903 if ((current > range.upper || !haveUpper) && current > 0)
16904 {
16905 range.upper = current;
16906 haveUpper = true;
16907 }
16602 }
16908 }
16603 if ((current > range.upper || !haveUpper) && current > 0)
16909 ++it;
16910 }
16911 }
16912
16913 foundRange = haveLower && haveUpper;
16914 return range;
16915 }
16916
16917 QCPRange QCPGraph::getKeyRangeVector(bool &foundRange, SignDomain inSignDomain, bool includeErrors) const
16918 {
16919 QCPRange range;
16920 bool haveLower = false;
16921 bool haveUpper = false;
16922
16923 double current, currentErrorMinus, currentErrorPlus;
16924
16925 if (inSignDomain == sdBoth) // range may be anywhere
16926 {
16927 QVector<QCPData>::const_iterator it = mDataVector->constBegin();
16928 while (it != mDataVector->constEnd())
16929 {
16930 current = (*it).key;
16931 currentErrorMinus = (includeErrors ? (*it).keyErrorMinus : 0);
16932 currentErrorPlus = (includeErrors ? (*it).keyErrorPlus : 0);
16933 if (current-currentErrorMinus < range.lower || !haveLower)
16934 {
16935 range.lower = current-currentErrorMinus;
16936 haveLower = true;
16937 }
16938 if (current+currentErrorPlus > range.upper || !haveUpper)
16939 {
16940 range.upper = current+currentErrorPlus;
16941 haveUpper = true;
16942 }
16943 ++it;
16944 }
16945 } else if (inSignDomain == sdNegative) // range may only be in the negative sign domain
16946 {
16947 QVector<QCPData>::const_iterator it = mDataVector->constBegin();
16948 while (it != mDataVector->constEnd())
16949 {
16950 current = (*it).key;
16951 currentErrorMinus = (includeErrors ? (*it).keyErrorMinus : 0);
16952 currentErrorPlus = (includeErrors ? (*it).keyErrorPlus : 0);
16953 if ((current-currentErrorMinus < range.lower || !haveLower) && current-currentErrorMinus < 0)
16954 {
16955 range.lower = current-currentErrorMinus;
16956 haveLower = true;
16957 }
16958 if ((current+currentErrorPlus > range.upper || !haveUpper) && current+currentErrorPlus < 0)
16959 {
16960 range.upper = current+currentErrorPlus;
16961 haveUpper = true;
16962 }
16963 if (includeErrors) // in case point is in valid sign domain but errobars stretch beyond it, we still want to geht that point.
16964 {
16965 if ((current < range.lower || !haveLower) && current < 0)
16966 {
16604 {
16967 range.lower = current;
16605 range.upper = current;
16968 haveLower = true;
16606 haveUpper = true;
16969 }
16970 if ((current > range.upper || !haveUpper) && current < 0)
16971 {
16972 range.upper = current;
16973 haveUpper = true;
16974 }
16607 }
16975 }
16608 }
16976 ++it;
16609 ++it;
16977 }
16610 }
16978 } else if (inSignDomain == sdPositive) // range may only be in the positive sign domain
16611 }
16979 {
16612
16980 QVector<QCPData>::const_iterator it = mDataVector->constBegin();
16613 foundRange = haveLower && haveUpper;
16981 while (it != mDataVector->constEnd())
16614 return range;
16982 {
16983 current = (*it).key;
16984 currentErrorMinus = (includeErrors ? (*it).keyErrorMinus : 0);
16985 currentErrorPlus = (includeErrors ? (*it).keyErrorPlus : 0);
16986 if ((current-currentErrorMinus < range.lower || !haveLower) && current-currentErrorMinus > 0)
16987 {
16988 range.lower = current-currentErrorMinus;
16989 haveLower = true;
16990 }
16991 if ((current+currentErrorPlus > range.upper || !haveUpper) && current+currentErrorPlus > 0)
16992 {
16993 range.upper = current+currentErrorPlus;
16994 haveUpper = true;
16995 }
16996 if (includeErrors) // in case point is in valid sign domain but errobars stretch beyond it, we still want to get that point.
16997 {
16998 if ((current < range.lower || !haveLower) && current > 0)
16999 {
17000 range.lower = current;
17001 haveLower = true;
17002 }
17003 if ((current > range.upper || !haveUpper) && current > 0)
17004 {
17005 range.upper = current;
17006 haveUpper = true;
17007 }
17008 }
17009 ++it;
17010 }
17011 }
17012
17013 foundRange = haveLower && haveUpper;
17014 return range;
17015 }
16615 }
17016
16616
17017 /*! \overload
16617 /*! \overload
@@ -17022,203 +16622,104 QCPRange QCPGraph::getKeyRangeVector(boo
17022 */
16622 */
17023 QCPRange QCPGraph::getValueRange(bool &foundRange, SignDomain inSignDomain, bool includeErrors) const
16623 QCPRange QCPGraph::getValueRange(bool &foundRange, SignDomain inSignDomain, bool includeErrors) const
17024 {
16624 {
17025 QCPRange range;
16625 QCPRange range;
17026 bool haveLower = false;
16626 bool haveLower = false;
17027 bool haveUpper = false;
16627 bool haveUpper = false;
17028
16628
17029 double current, currentErrorMinus, currentErrorPlus;
16629 double current, currentErrorMinus, currentErrorPlus;
17030
16630
17031 if (inSignDomain == sdBoth) // range may be anywhere
16631 if (inSignDomain == sdBoth) // range may be anywhere
17032 {
16632 {
17033 QCPDataMap::const_iterator it = mData->constBegin();
16633 QCPDataMap::const_iterator it = mData->constBegin();
17034 while (it != mData->constEnd())
16634 while (it != mData->constEnd())
17035 {
16635 {
17036 current = it.value().value;
16636 current = it.value().value;
17037 currentErrorMinus = (includeErrors ? it.value().valueErrorMinus : 0);
16637 currentErrorMinus = (includeErrors ? it.value().valueErrorMinus : 0);
17038 currentErrorPlus = (includeErrors ? it.value().valueErrorPlus : 0);
16638 currentErrorPlus = (includeErrors ? it.value().valueErrorPlus : 0);
17039 if (current-currentErrorMinus < range.lower || !haveLower)
16639 if (current-currentErrorMinus < range.lower || !haveLower)
17040 {
16640 {
17041 range.lower = current-currentErrorMinus;
16641 range.lower = current-currentErrorMinus;
17042 haveLower = true;
16642 haveLower = true;
17043 }
16643 }
17044 if (current+currentErrorPlus > range.upper || !haveUpper)
16644 if (current+currentErrorPlus > range.upper || !haveUpper)
17045 {
16645 {
17046 range.upper = current+currentErrorPlus;
16646 range.upper = current+currentErrorPlus;
17047 haveUpper = true;
16647 haveUpper = true;
17048 }
16648 }
17049 ++it;
16649 ++it;
17050 }
16650 }
17051 } else if (inSignDomain == sdNegative) // range may only be in the negative sign domain
16651 } else if (inSignDomain == sdNegative) // range may only be in the negative sign domain
17052 {
16652 {
17053 QCPDataMap::const_iterator it = mData->constBegin();
16653 QCPDataMap::const_iterator it = mData->constBegin();
17054 while (it != mData->constEnd())
16654 while (it != mData->constEnd())
17055 {
16655 {
17056 current = it.value().value;
16656 current = it.value().value;
17057 currentErrorMinus = (includeErrors ? it.value().valueErrorMinus : 0);
16657 currentErrorMinus = (includeErrors ? it.value().valueErrorMinus : 0);
17058 currentErrorPlus = (includeErrors ? it.value().valueErrorPlus : 0);
16658 currentErrorPlus = (includeErrors ? it.value().valueErrorPlus : 0);
17059 if ((current-currentErrorMinus < range.lower || !haveLower) && current-currentErrorMinus < 0)
16659 if ((current-currentErrorMinus < range.lower || !haveLower) && current-currentErrorMinus < 0)
17060 {
16660 {
17061 range.lower = current-currentErrorMinus;
16661 range.lower = current-currentErrorMinus;
17062 haveLower = true;
16662 haveLower = true;
17063 }
16663 }
17064 if ((current+currentErrorPlus > range.upper || !haveUpper) && current+currentErrorPlus < 0)
16664 if ((current+currentErrorPlus > range.upper || !haveUpper) && current+currentErrorPlus < 0)
17065 {
16665 {
17066 range.upper = current+currentErrorPlus;
16666 range.upper = current+currentErrorPlus;
17067 haveUpper = true;
16667 haveUpper = true;
17068 }
16668 }
17069 if (includeErrors) // in case point is in valid sign domain but errobars stretch beyond it, we still want to get that point.
16669 if (includeErrors) // in case point is in valid sign domain but errobars stretch beyond it, we still want to get that point.
17070 {
16670 {
17071 if ((current < range.lower || !haveLower) && current < 0)
16671 if ((current < range.lower || !haveLower) && current < 0)
17072 {
16672 {
17073 range.lower = current;
16673 range.lower = current;
17074 haveLower = true;
16674 haveLower = true;
17075 }
16675 }
17076 if ((current > range.upper || !haveUpper) && current < 0)
16676 if ((current > range.upper || !haveUpper) && current < 0)
17077 {
16677 {
17078 range.upper = current;
16678 range.upper = current;
17079 haveUpper = true;
16679 haveUpper = true;
17080 }
16680 }
17081 }
16681 }
17082 ++it;
16682 ++it;
17083 }
16683 }
17084 } else if (inSignDomain == sdPositive) // range may only be in the positive sign domain
16684 } else if (inSignDomain == sdPositive) // range may only be in the positive sign domain
17085 {
16685 {
17086 QCPDataMap::const_iterator it = mData->constBegin();
16686 QCPDataMap::const_iterator it = mData->constBegin();
17087 while (it != mData->constEnd())
16687 while (it != mData->constEnd())
17088 {
16688 {
17089 current = it.value().value;
16689 current = it.value().value;
17090 currentErrorMinus = (includeErrors ? it.value().valueErrorMinus : 0);
16690 currentErrorMinus = (includeErrors ? it.value().valueErrorMinus : 0);
17091 currentErrorPlus = (includeErrors ? it.value().valueErrorPlus : 0);
16691 currentErrorPlus = (includeErrors ? it.value().valueErrorPlus : 0);
17092 if ((current-currentErrorMinus < range.lower || !haveLower) && current-currentErrorMinus > 0)
16692 if ((current-currentErrorMinus < range.lower || !haveLower) && current-currentErrorMinus > 0)
17093 {
16693 {
17094 range.lower = current-currentErrorMinus;
16694 range.lower = current-currentErrorMinus;
17095 haveLower = true;
16695 haveLower = true;
17096 }
16696 }
17097 if ((current+currentErrorPlus > range.upper || !haveUpper) && current+currentErrorPlus > 0)
16697 if ((current+currentErrorPlus > range.upper || !haveUpper) && current+currentErrorPlus > 0)
17098 {
16698 {
17099 range.upper = current+currentErrorPlus;
16699 range.upper = current+currentErrorPlus;
17100 haveUpper = true;
16700 haveUpper = true;
17101 }
16701 }
17102 if (includeErrors) // in case point is in valid sign domain but errobars stretch beyond it, we still want to geht that point.
16702 if (includeErrors) // in case point is in valid sign domain but errobars stretch beyond it, we still want to geht that point.
17103 {
16703 {
17104 if ((current < range.lower || !haveLower) && current > 0)
16704 if ((current < range.lower || !haveLower) && current > 0)
17105 {
16705 {
17106 range.lower = current;
16706 range.lower = current;
17107 haveLower = true;
16707 haveLower = true;
17108 }
17109 if ((current > range.upper || !haveUpper) && current > 0)
17110 {
17111 range.upper = current;
17112 haveUpper = true;
17113 }
16708 }
17114 }
16709 if ((current > range.upper || !haveUpper) && current > 0)
17115 ++it;
17116 }
17117 }
17118
17119 foundRange = haveLower && haveUpper;
17120 return range;
17121 }
17122
17123 QCPRange QCPGraph::getValueRangeVector(bool &foundRange, SignDomain inSignDomain, bool includeErrors) const
17124 {
17125 QCPRange range;
17126 bool haveLower = false;
17127 bool haveUpper = false;
17128
17129 double current, currentErrorMinus, currentErrorPlus;
17130
17131 if (inSignDomain == sdBoth) // range may be anywhere
17132 {
17133 QVector<QCPData>::const_iterator it = mDataVector->constBegin();
17134 while (it != mDataVector->constEnd())
17135 {
17136 current = (*it).value;
17137 currentErrorMinus = (includeErrors ? (*it).valueErrorMinus : 0);
17138 currentErrorPlus = (includeErrors ? (*it).valueErrorPlus : 0);
17139 if (current-currentErrorMinus < range.lower || !haveLower)
17140 {
17141 range.lower = current-currentErrorMinus;
17142 haveLower = true;
17143 }
17144 if (current+currentErrorPlus > range.upper || !haveUpper)
17145 {
17146 range.upper = current+currentErrorPlus;
17147 haveUpper = true;
17148 }
17149 ++it;
17150 }
17151 } else if (inSignDomain == sdNegative) // range may only be in the negative sign domain
17152 {
17153 QVector<QCPData>::const_iterator it = mDataVector->constBegin();
17154 while (it != mDataVector->constEnd())
17155 {
17156 current = (*it).value;
17157 currentErrorMinus = (includeErrors ? (*it).valueErrorMinus : 0);
17158 currentErrorPlus = (includeErrors ? (*it).valueErrorPlus : 0);
17159 if ((current-currentErrorMinus < range.lower || !haveLower) && current-currentErrorMinus < 0)
17160 {
17161 range.lower = current-currentErrorMinus;
17162 haveLower = true;
17163 }
17164 if ((current+currentErrorPlus > range.upper || !haveUpper) && current+currentErrorPlus < 0)
17165 {
17166 range.upper = current+currentErrorPlus;
17167 haveUpper = true;
17168 }
17169 if (includeErrors) // in case point is in valid sign domain but errobars stretch beyond it, we still want to get that point.
17170 {
17171 if ((current < range.lower || !haveLower) && current < 0)
17172 {
16710 {
17173 range.lower = current;
16711 range.upper = current;
17174 haveLower = true;
16712 haveUpper = true;
17175 }
17176 if ((current > range.upper || !haveUpper) && current < 0)
17177 {
17178 range.upper = current;
17179 haveUpper = true;
17180 }
16713 }
17181 }
16714 }
17182 ++it;
16715 ++it;
17183 }
16716 }
17184 } else if (inSignDomain == sdPositive) // range may only be in the positive sign domain
16717 }
17185 {
16718
17186 QVector<QCPData>::const_iterator it = mDataVector->constBegin();
16719 foundRange = haveLower && haveUpper;
17187 while (it != mDataVector->constEnd())
16720 return range;
17188 {
16721 }
17189 current = (*it).value;
16722
17190 currentErrorMinus = (includeErrors ? (*it).valueErrorMinus : 0);
17191 currentErrorPlus = (includeErrors ? (*it).valueErrorPlus : 0);
17192 if ((current-currentErrorMinus < range.lower || !haveLower) && current-currentErrorMinus > 0)
17193 {
17194 range.lower = current-currentErrorMinus;
17195 haveLower = true;
17196 }
17197 if ((current+currentErrorPlus > range.upper || !haveUpper) && current+currentErrorPlus > 0)
17198 {
17199 range.upper = current+currentErrorPlus;
17200 haveUpper = true;
17201 }
17202 if (includeErrors) // in case point is in valid sign domain but errobars stretch beyond it, we still want to geht that point.
17203 {
17204 if ((current < range.lower || !haveLower) && current > 0)
17205 {
17206 range.lower = current;
17207 haveLower = true;
17208 }
17209 if ((current > range.upper || !haveUpper) && current > 0)
17210 {
17211 range.upper = current;
17212 haveUpper = true;
17213 }
17214 }
17215 ++it;
17216 }
17217 }
17218
17219 foundRange = haveLower && haveUpper;
17220 return range;
17221 }
17222
16723
17223 ////////////////////////////////////////////////////////////////////////////////////////////////////
16724 ////////////////////////////////////////////////////////////////////////////////////////////////////
17224 //////////////////// QCPCurveData
16725 //////////////////// QCPCurveData
@@ -17241,9 +16742,9 QCPRange QCPGraph::getValueRangeVector(b
17241 Constructs a curve data point with t, key and value set to zero.
16742 Constructs a curve data point with t, key and value set to zero.
17242 */
16743 */
17243 QCPCurveData::QCPCurveData() :
16744 QCPCurveData::QCPCurveData() :
17244 t(0),
16745 t(0),
17245 key(0),
16746 key(0),
17246 value(0)
16747 value(0)
17247 {
16748 {
17248 }
16749 }
17249
16750
@@ -17251,9 +16752,9 QCPCurveData::QCPCurveData() :
17251 Constructs a curve data point with the specified \a t, \a key and \a value.
16752 Constructs a curve data point with the specified \a t, \a key and \a value.
17252 */
16753 */
17253 QCPCurveData::QCPCurveData(double t, double key, double value) :
16754 QCPCurveData::QCPCurveData(double t, double key, double value) :
17254 t(t),
16755 t(t),
17255 key(key),
16756 key(key),
17256 value(value)
16757 value(value)
17257 {
16758 {
17258 }
16759 }
17259
16760
@@ -17304,25 +16805,25 QCPCurveData::QCPCurveData(double t, dou
17304 then takes ownership of the graph.
16805 then takes ownership of the graph.
17305 */
16806 */
17306 QCPCurve::QCPCurve(QCPAxis *keyAxis, QCPAxis *valueAxis) :
16807 QCPCurve::QCPCurve(QCPAxis *keyAxis, QCPAxis *valueAxis) :
17307 QCPAbstractPlottable(keyAxis, valueAxis)
16808 QCPAbstractPlottable(keyAxis, valueAxis)
17308 {
16809 {
17309 mData = new QCPCurveDataMap;
16810 mData = new QCPCurveDataMap;
17310 mPen.setColor(Qt::blue);
16811 mPen.setColor(Qt::blue);
17311 mPen.setStyle(Qt::SolidLine);
16812 mPen.setStyle(Qt::SolidLine);
17312 mBrush.setColor(Qt::blue);
16813 mBrush.setColor(Qt::blue);
17313 mBrush.setStyle(Qt::NoBrush);
16814 mBrush.setStyle(Qt::NoBrush);
17314 mSelectedPen = mPen;
16815 mSelectedPen = mPen;
17315 mSelectedPen.setWidthF(2.5);
16816 mSelectedPen.setWidthF(2.5);
17316 mSelectedPen.setColor(QColor(80, 80, 255)); // lighter than Qt::blue of mPen
16817 mSelectedPen.setColor(QColor(80, 80, 255)); // lighter than Qt::blue of mPen
17317 mSelectedBrush = mBrush;
16818 mSelectedBrush = mBrush;
17318
16819
17319 setScatterStyle(QCPScatterStyle());
16820 setScatterStyle(QCPScatterStyle());
17320 setLineStyle(lsLine);
16821 setLineStyle(lsLine);
17321 }
16822 }
17322
16823
17323 QCPCurve::~QCPCurve()
16824 QCPCurve::~QCPCurve()
17324 {
16825 {
17325 delete mData;
16826 delete mData;
17326 }
16827 }
17327
16828
17328 /*!
16829 /*!
@@ -17334,18 +16835,18 QCPCurve::~QCPCurve()
17334 */
16835 */
17335 void QCPCurve::setData(QCPCurveDataMap *data, bool copy)
16836 void QCPCurve::setData(QCPCurveDataMap *data, bool copy)
17336 {
16837 {
17337 if (mData == data)
16838 if (mData == data)
17338 {
16839 {
17339 qDebug() << Q_FUNC_INFO << "The data pointer is already in (and owned by) this plottable" << reinterpret_cast<quintptr>(data);
16840 qDebug() << Q_FUNC_INFO << "The data pointer is already in (and owned by) this plottable" << reinterpret_cast<quintptr>(data);
17340 return;
16841 return;
17341 }
16842 }
17342 if (copy)
16843 if (copy)
17343 {
16844 {
17344 *mData = *data;
16845 *mData = *data;
17345 } else
16846 } else
17346 {
16847 {
17347 delete mData;
16848 delete mData;
17348 mData = data;
16849 mData = data;
17349 }
16850 }
17350 }
16851 }
17351
16852
@@ -17357,17 +16858,17 void QCPCurve::setData(QCPCurveDataMap *
17357 */
16858 */
17358 void QCPCurve::setData(const QVector<double> &t, const QVector<double> &key, const QVector<double> &value)
16859 void QCPCurve::setData(const QVector<double> &t, const QVector<double> &key, const QVector<double> &value)
17359 {
16860 {
17360 mData->clear();
16861 mData->clear();
17361 int n = t.size();
16862 int n = t.size();
17362 n = qMin(n, key.size());
16863 n = qMin(n, key.size());
17363 n = qMin(n, value.size());
16864 n = qMin(n, value.size());
17364 QCPCurveData newData;
16865 QCPCurveData newData;
17365 for (int i=0; i<n; ++i)
16866 for (int i=0; i<n; ++i)
17366 {
16867 {
17367 newData.t = t[i];
16868 newData.t = t[i];
17368 newData.key = key[i];
16869 newData.key = key[i];
17369 newData.value = value[i];
16870 newData.value = value[i];
17370 mData->insertMulti(newData.t, newData);
16871 mData->insertMulti(newData.t, newData);
17371 }
16872 }
17372 }
16873 }
17373
16874
@@ -17378,16 +16879,16 void QCPCurve::setData(const QVector<dou
17378 */
16879 */
17379 void QCPCurve::setData(const QVector<double> &key, const QVector<double> &value)
16880 void QCPCurve::setData(const QVector<double> &key, const QVector<double> &value)
17380 {
16881 {
17381 mData->clear();
16882 mData->clear();
17382 int n = key.size();
16883 int n = key.size();
17383 n = qMin(n, value.size());
16884 n = qMin(n, value.size());
17384 QCPCurveData newData;
16885 QCPCurveData newData;
17385 for (int i=0; i<n; ++i)
16886 for (int i=0; i<n; ++i)
17386 {
16887 {
17387 newData.t = i; // no t vector given, so we assign t the index of the key/value pair
16888 newData.t = i; // no t vector given, so we assign t the index of the key/value pair
17388 newData.key = key[i];
16889 newData.key = key[i];
17389 newData.value = value[i];
16890 newData.value = value[i];
17390 mData->insertMulti(newData.t, newData);
16891 mData->insertMulti(newData.t, newData);
17391 }
16892 }
17392 }
16893 }
17393
16894
@@ -17400,7 +16901,7 void QCPCurve::setData(const QVector<dou
17400 */
16901 */
17401 void QCPCurve::setScatterStyle(const QCPScatterStyle &style)
16902 void QCPCurve::setScatterStyle(const QCPScatterStyle &style)
17402 {
16903 {
17403 mScatterStyle = style;
16904 mScatterStyle = style;
17404 }
16905 }
17405
16906
17406 /*!
16907 /*!
@@ -17412,7 +16913,7 void QCPCurve::setScatterStyle(const QCP
17412 */
16913 */
17413 void QCPCurve::setLineStyle(QCPCurve::LineStyle style)
16914 void QCPCurve::setLineStyle(QCPCurve::LineStyle style)
17414 {
16915 {
17415 mLineStyle = style;
16916 mLineStyle = style;
17416 }
16917 }
17417
16918
17418 /*!
16919 /*!
@@ -17421,7 +16922,7 void QCPCurve::setLineStyle(QCPCurve::Li
17421 */
16922 */
17422 void QCPCurve::addData(const QCPCurveDataMap &dataMap)
16923 void QCPCurve::addData(const QCPCurveDataMap &dataMap)
17423 {
16924 {
17424 mData->unite(dataMap);
16925 mData->unite(dataMap);
17425 }
16926 }
17426
16927
17427 /*! \overload
16928 /*! \overload
@@ -17430,7 +16931,7 void QCPCurve::addData(const QCPCurveDat
17430 */
16931 */
17431 void QCPCurve::addData(const QCPCurveData &data)
16932 void QCPCurve::addData(const QCPCurveData &data)
17432 {
16933 {
17433 mData->insertMulti(data.t, data);
16934 mData->insertMulti(data.t, data);
17434 }
16935 }
17435
16936
17436 /*! \overload
16937 /*! \overload
@@ -17439,11 +16940,11 void QCPCurve::addData(const QCPCurveDat
17439 */
16940 */
17440 void QCPCurve::addData(double t, double key, double value)
16941 void QCPCurve::addData(double t, double key, double value)
17441 {
16942 {
17442 QCPCurveData newData;
16943 QCPCurveData newData;
17443 newData.t = t;
16944 newData.t = t;
17444 newData.key = key;
16945 newData.key = key;
17445 newData.value = value;
16946 newData.value = value;
17446 mData->insertMulti(newData.t, newData);
16947 mData->insertMulti(newData.t, newData);
17447 }
16948 }
17448
16949
17449 /*! \overload
16950 /*! \overload
@@ -17456,14 +16957,14 void QCPCurve::addData(double t, double
17456 */
16957 */
17457 void QCPCurve::addData(double key, double value)
16958 void QCPCurve::addData(double key, double value)
17458 {
16959 {
17459 QCPCurveData newData;
16960 QCPCurveData newData;
17460 if (!mData->isEmpty())
16961 if (!mData->isEmpty())
17461 newData.t = (mData->constEnd()-1).key()+1;
16962 newData.t = (mData->constEnd()-1).key()+1;
17462 else
16963 else
17463 newData.t = 0;
16964 newData.t = 0;
17464 newData.key = key;
16965 newData.key = key;
17465 newData.value = value;
16966 newData.value = value;
17466 mData->insertMulti(newData.t, newData);
16967 mData->insertMulti(newData.t, newData);
17467 }
16968 }
17468
16969
17469 /*! \overload
16970 /*! \overload
@@ -17472,16 +16973,16 void QCPCurve::addData(double key, doubl
17472 */
16973 */
17473 void QCPCurve::addData(const QVector<double> &ts, const QVector<double> &keys, const QVector<double> &values)
16974 void QCPCurve::addData(const QVector<double> &ts, const QVector<double> &keys, const QVector<double> &values)
17474 {
16975 {
17475 int n = ts.size();
16976 int n = ts.size();
17476 n = qMin(n, keys.size());
16977 n = qMin(n, keys.size());
17477 n = qMin(n, values.size());
16978 n = qMin(n, values.size());
17478 QCPCurveData newData;
16979 QCPCurveData newData;
17479 for (int i=0; i<n; ++i)
16980 for (int i=0; i<n; ++i)
17480 {
16981 {
17481 newData.t = ts[i];
16982 newData.t = ts[i];
17482 newData.key = keys[i];
16983 newData.key = keys[i];
17483 newData.value = values[i];
16984 newData.value = values[i];
17484 mData->insertMulti(newData.t, newData);
16985 mData->insertMulti(newData.t, newData);
17485 }
16986 }
17486 }
16987 }
17487
16988
@@ -17491,9 +16992,9 void QCPCurve::addData(const QVector<dou
17491 */
16992 */
17492 void QCPCurve::removeDataBefore(double t)
16993 void QCPCurve::removeDataBefore(double t)
17493 {
16994 {
17494 QCPCurveDataMap::iterator it = mData->begin();
16995 QCPCurveDataMap::iterator it = mData->begin();
17495 while (it != mData->end() && it.key() < t)
16996 while (it != mData->end() && it.key() < t)
17496 it = mData->erase(it);
16997 it = mData->erase(it);
17497 }
16998 }
17498
16999
17499 /*!
17000 /*!
@@ -17502,10 +17003,10 void QCPCurve::removeDataBefore(double t
17502 */
17003 */
17503 void QCPCurve::removeDataAfter(double t)
17004 void QCPCurve::removeDataAfter(double t)
17504 {
17005 {
17505 if (mData->isEmpty()) return;
17006 if (mData->isEmpty()) return;
17506 QCPCurveDataMap::iterator it = mData->upperBound(t);
17007 QCPCurveDataMap::iterator it = mData->upperBound(t);
17507 while (it != mData->end())
17008 while (it != mData->end())
17508 it = mData->erase(it);
17009 it = mData->erase(it);
17509 }
17010 }
17510
17011
17511 /*!
17012 /*!
@@ -17517,11 +17018,11 void QCPCurve::removeDataAfter(double t)
17517 */
17018 */
17518 void QCPCurve::removeData(double fromt, double tot)
17019 void QCPCurve::removeData(double fromt, double tot)
17519 {
17020 {
17520 if (fromt >= tot || mData->isEmpty()) return;
17021 if (fromt >= tot || mData->isEmpty()) return;
17521 QCPCurveDataMap::iterator it = mData->upperBound(fromt);
17022 QCPCurveDataMap::iterator it = mData->upperBound(fromt);
17522 QCPCurveDataMap::iterator itEnd = mData->upperBound(tot);
17023 QCPCurveDataMap::iterator itEnd = mData->upperBound(tot);
17523 while (it != itEnd)
17024 while (it != itEnd)
17524 it = mData->erase(it);
17025 it = mData->erase(it);
17525 }
17026 }
17526
17027
17527 /*! \overload
17028 /*! \overload
@@ -17535,7 +17036,7 void QCPCurve::removeData(double fromt,
17535 */
17036 */
17536 void QCPCurve::removeData(double t)
17037 void QCPCurve::removeData(double t)
17537 {
17038 {
17538 mData->remove(t);
17039 mData->remove(t);
17539 }
17040 }
17540
17041
17541 /*!
17042 /*!
@@ -17544,134 +17045,134 void QCPCurve::removeData(double t)
17544 */
17045 */
17545 void QCPCurve::clearData()
17046 void QCPCurve::clearData()
17546 {
17047 {
17547 mData->clear();
17048 mData->clear();
17548 }
17049 }
17549
17050
17550 /* inherits documentation from base class */
17051 /* inherits documentation from base class */
17551 double QCPCurve::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
17052 double QCPCurve::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
17552 {
17053 {
17553 Q_UNUSED(details)
17054 Q_UNUSED(details)
17554 if ((onlySelectable && !mSelectable) || mData->isEmpty())
17055 if ((onlySelectable && !mSelectable) || mData->isEmpty())
17555 return -1;
17056 return -1;
17556 if (!mKeyAxis || !mValueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return -1; }
17057 if (!mKeyAxis || !mValueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return -1; }
17557
17058
17558 if (mKeyAxis.data()->axisRect()->rect().contains(pos.toPoint()))
17059 if (mKeyAxis.data()->axisRect()->rect().contains(pos.toPoint()))
17559 return pointDistance(pos);
17060 return pointDistance(pos);
17560 else
17061 else
17561 return -1;
17062 return -1;
17562 }
17063 }
17563
17064
17564 /* inherits documentation from base class */
17065 /* inherits documentation from base class */
17565 void QCPCurve::draw(QCPPainter *painter)
17066 void QCPCurve::draw(QCPPainter *painter)
17566 {
17067 {
17567 if (mData->isEmpty()) return;
17068 if (mData->isEmpty()) return;
17568
17069
17569 // allocate line vector:
17070 // allocate line vector:
17570 QVector<QPointF> *lineData = new QVector<QPointF>;
17071 QVector<QPointF> *lineData = new QVector<QPointF>;
17571
17072
17572 // fill with curve data:
17073 // fill with curve data:
17573 getCurveData(lineData);
17074 getCurveData(lineData);
17574
17075
17575 // check data validity if flag set:
17076 // check data validity if flag set:
17576 #ifdef QCUSTOMPLOT_CHECK_DATA
17077 #ifdef QCUSTOMPLOT_CHECK_DATA
17577 QCPCurveDataMap::const_iterator it;
17078 QCPCurveDataMap::const_iterator it;
17578 for (it = mData->constBegin(); it != mData->constEnd(); ++it)
17079 for (it = mData->constBegin(); it != mData->constEnd(); ++it)
17579 {
17080 {
17580 if (QCP::isInvalidData(it.value().t) ||
17081 if (QCP::isInvalidData(it.value().t) ||
17581 QCP::isInvalidData(it.value().key, it.value().value))
17082 QCP::isInvalidData(it.value().key, it.value().value))
17582 qDebug() << Q_FUNC_INFO << "Data point at" << it.key() << "invalid." << "Plottable name:" << name();
17083 qDebug() << Q_FUNC_INFO << "Data point at" << it.key() << "invalid." << "Plottable name:" << name();
17583 }
17084 }
17584 #endif
17085 #endif
17585
17086
17586 // draw curve fill:
17087 // draw curve fill:
17587 if (mainBrush().style() != Qt::NoBrush && mainBrush().color().alpha() != 0)
17088 if (mainBrush().style() != Qt::NoBrush && mainBrush().color().alpha() != 0)
17588 {
17089 {
17589 applyFillAntialiasingHint(painter);
17090 applyFillAntialiasingHint(painter);
17590 painter->setPen(Qt::NoPen);
17091 painter->setPen(Qt::NoPen);
17591 painter->setBrush(mainBrush());
17092 painter->setBrush(mainBrush());
17592 painter->drawPolygon(QPolygonF(*lineData));
17093 painter->drawPolygon(QPolygonF(*lineData));
17593 }
17094 }
17594
17095
17595 // draw curve line:
17096 // draw curve line:
17596 if (mLineStyle != lsNone && mainPen().style() != Qt::NoPen && mainPen().color().alpha() != 0)
17097 if (mLineStyle != lsNone && mainPen().style() != Qt::NoPen && mainPen().color().alpha() != 0)
17597 {
17098 {
17598 applyDefaultAntialiasingHint(painter);
17099 applyDefaultAntialiasingHint(painter);
17599 painter->setPen(mainPen());
17100 painter->setPen(mainPen());
17600 painter->setBrush(Qt::NoBrush);
17101 painter->setBrush(Qt::NoBrush);
17601 // if drawing solid line and not in PDF, use much faster line drawing instead of polyline:
17102 // if drawing solid line and not in PDF, use much faster line drawing instead of polyline:
17602 if (mParentPlot->plottingHints().testFlag(QCP::phFastPolylines) &&
17103 if (mParentPlot->plottingHints().testFlag(QCP::phFastPolylines) &&
17603 painter->pen().style() == Qt::SolidLine &&
17104 painter->pen().style() == Qt::SolidLine &&
17604 !painter->modes().testFlag(QCPPainter::pmVectorized) &&
17105 !painter->modes().testFlag(QCPPainter::pmVectorized) &&
17605 !painter->modes().testFlag(QCPPainter::pmNoCaching))
17106 !painter->modes().testFlag(QCPPainter::pmNoCaching))
17606 {
17107 {
17607 int i = 1;
17108 int i = 1;
17608 int lineDataSize = lineData->size();
17109 int lineDataSize = lineData->size();
17609 while (i < lineDataSize)
17110 while (i < lineDataSize)
17610 {
17111 {
17611 if (!qIsNaN(lineData->at(i).y()) && !qIsNaN(lineData->at(i).x())) // NaNs create a gap in the line
17112 if (!qIsNaN(lineData->at(i).y()) && !qIsNaN(lineData->at(i).x())) // NaNs create a gap in the line
17612 painter->drawLine(lineData->at(i-1), lineData->at(i));
17113 painter->drawLine(lineData->at(i-1), lineData->at(i));
17613 else
17114 else
17115 ++i;
17614 ++i;
17116 ++i;
17615 ++i;
17616 }
17117 }
17617 } else
17118 } else
17618 {
17119 {
17619 int segmentStart = 0;
17120 int segmentStart = 0;
17620 int i = 0;
17121 int i = 0;
17621 int lineDataSize = lineData->size();
17122 int lineDataSize = lineData->size();
17622 while (i < lineDataSize)
17123 while (i < lineDataSize)
17623 {
17124 {
17624 if (qIsNaN(lineData->at(i).y()) || qIsNaN(lineData->at(i).x())) // NaNs create a gap in the line
17125 if (qIsNaN(lineData->at(i).y()) || qIsNaN(lineData->at(i).x())) // NaNs create a gap in the line
17625 {
17126 {
17626 painter->drawPolyline(lineData->constData()+segmentStart, i-segmentStart); // i, because we don't want to include the current NaN point
17127 painter->drawPolyline(lineData->constData()+segmentStart, i-segmentStart); // i, because we don't want to include the current NaN point
17627 segmentStart = i+1;
17128 segmentStart = i+1;
17628 }
17129 }
17629 ++i;
17130 ++i;
17630 }
17131 }
17631 // draw last segment:
17132 // draw last segment:
17632 painter->drawPolyline(lineData->constData()+segmentStart, lineDataSize-segmentStart); // lineDataSize, because we do want to include the last point
17133 painter->drawPolyline(lineData->constData()+segmentStart, lineDataSize-segmentStart); // lineDataSize, because we do want to include the last point
17633 }
17134 }
17634 }
17135 }
17635
17136
17636 // draw scatters:
17137 // draw scatters:
17637 if (!mScatterStyle.isNone())
17138 if (!mScatterStyle.isNone())
17638 drawScatterPlot(painter, lineData);
17139 drawScatterPlot(painter, lineData);
17639
17140
17640 // free allocated line data:
17141 // free allocated line data:
17641 delete lineData;
17142 delete lineData;
17642 }
17143 }
17643
17144
17644 /* inherits documentation from base class */
17145 /* inherits documentation from base class */
17645 void QCPCurve::drawLegendIcon(QCPPainter *painter, const QRectF &rect) const
17146 void QCPCurve::drawLegendIcon(QCPPainter *painter, const QRectF &rect) const
17646 {
17147 {
17647 // draw fill:
17148 // draw fill:
17648 if (mBrush.style() != Qt::NoBrush)
17149 if (mBrush.style() != Qt::NoBrush)
17649 {
17150 {
17650 applyFillAntialiasingHint(painter);
17151 applyFillAntialiasingHint(painter);
17651 painter->fillRect(QRectF(rect.left(), rect.top()+rect.height()/2.0, rect.width(), rect.height()/3.0), mBrush);
17152 painter->fillRect(QRectF(rect.left(), rect.top()+rect.height()/2.0, rect.width(), rect.height()/3.0), mBrush);
17652 }
17153 }
17653 // draw line vertically centered:
17154 // draw line vertically centered:
17654 if (mLineStyle != lsNone)
17155 if (mLineStyle != lsNone)
17655 {
17156 {
17656 applyDefaultAntialiasingHint(painter);
17157 applyDefaultAntialiasingHint(painter);
17657 painter->setPen(mPen);
17158 painter->setPen(mPen);
17658 painter->drawLine(QLineF(rect.left(), rect.top()+rect.height()/2.0, rect.right()+5, rect.top()+rect.height()/2.0)); // +5 on x2 else last segment is missing from dashed/dotted pens
17159 painter->drawLine(QLineF(rect.left(), rect.top()+rect.height()/2.0, rect.right()+5, rect.top()+rect.height()/2.0)); // +5 on x2 else last segment is missing from dashed/dotted pens
17659 }
17160 }
17660 // draw scatter symbol:
17161 // draw scatter symbol:
17661 if (!mScatterStyle.isNone())
17162 if (!mScatterStyle.isNone())
17662 {
17163 {
17663 applyScattersAntialiasingHint(painter);
17164 applyScattersAntialiasingHint(painter);
17664 // scale scatter pixmap if it's too large to fit in legend icon rect:
17165 // scale scatter pixmap if it's too large to fit in legend icon rect:
17665 if (mScatterStyle.shape() == QCPScatterStyle::ssPixmap && (mScatterStyle.pixmap().size().width() > rect.width() || mScatterStyle.pixmap().size().height() > rect.height()))
17166 if (mScatterStyle.shape() == QCPScatterStyle::ssPixmap && (mScatterStyle.pixmap().size().width() > rect.width() || mScatterStyle.pixmap().size().height() > rect.height()))
17666 {
17167 {
17667 QCPScatterStyle scaledStyle(mScatterStyle);
17168 QCPScatterStyle scaledStyle(mScatterStyle);
17668 scaledStyle.setPixmap(scaledStyle.pixmap().scaled(rect.size().toSize(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
17169 scaledStyle.setPixmap(scaledStyle.pixmap().scaled(rect.size().toSize(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
17669 scaledStyle.applyTo(painter, mPen);
17170 scaledStyle.applyTo(painter, mPen);
17670 scaledStyle.drawShape(painter, QRectF(rect).center());
17171 scaledStyle.drawShape(painter, QRectF(rect).center());
17671 } else
17172 } else
17672 {
17173 {
17673 mScatterStyle.applyTo(painter, mPen);
17174 mScatterStyle.applyTo(painter, mPen);
17674 mScatterStyle.drawShape(painter, QRectF(rect).center());
17175 mScatterStyle.drawShape(painter, QRectF(rect).center());
17675 }
17176 }
17676 }
17177 }
17677 }
17178 }
@@ -17683,12 +17184,12 void QCPCurve::drawLegendIcon(QCPPainter
17683 */
17184 */
17684 void QCPCurve::drawScatterPlot(QCPPainter *painter, const QVector<QPointF> *pointData) const
17185 void QCPCurve::drawScatterPlot(QCPPainter *painter, const QVector<QPointF> *pointData) const
17685 {
17186 {
17686 // draw scatter point symbols:
17187 // draw scatter point symbols:
17687 applyScattersAntialiasingHint(painter);
17188 applyScattersAntialiasingHint(painter);
17688 mScatterStyle.applyTo(painter, mPen);
17189 mScatterStyle.applyTo(painter, mPen);
17689 for (int i=0; i<pointData->size(); ++i)
17190 for (int i=0; i<pointData->size(); ++i)
17690 if (!qIsNaN(pointData->at(i).x()) && !qIsNaN(pointData->at(i).y()))
17191 if (!qIsNaN(pointData->at(i).x()) && !qIsNaN(pointData->at(i).y()))
17691 mScatterStyle.drawShape(painter, pointData->at(i));
17192 mScatterStyle.drawShape(painter, pointData->at(i));
17692 }
17193 }
17693
17194
17694 /*! \internal
17195 /*! \internal
@@ -17706,81 +17207,81 void QCPCurve::drawScatterPlot(QCPPainte
17706 */
17207 */
17707 void QCPCurve::getCurveData(QVector<QPointF> *lineData) const
17208 void QCPCurve::getCurveData(QVector<QPointF> *lineData) const
17708 {
17209 {
17709 QCPAxis *keyAxis = mKeyAxis.data();
17210 QCPAxis *keyAxis = mKeyAxis.data();
17710 QCPAxis *valueAxis = mValueAxis.data();
17211 QCPAxis *valueAxis = mValueAxis.data();
17711 if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
17212 if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
17712
17213
17713 // add margins to rect to compensate for stroke width
17214 // add margins to rect to compensate for stroke width
17714 double strokeMargin = qMax(qreal(1.0), qreal(mainPen().widthF()*0.75)); // stroke radius + 50% safety
17215 double strokeMargin = qMax(qreal(1.0), qreal(mainPen().widthF()*0.75)); // stroke radius + 50% safety
17715 if (!mScatterStyle.isNone())
17216 if (!mScatterStyle.isNone())
17716 strokeMargin = qMax(strokeMargin, mScatterStyle.size());
17217 strokeMargin = qMax(strokeMargin, mScatterStyle.size());
17717 double rectLeft = keyAxis->pixelToCoord(keyAxis->coordToPixel(keyAxis->range().lower)-strokeMargin*((keyAxis->orientation()==Qt::Vertical)!=keyAxis->rangeReversed()?-1:1));
17218 double rectLeft = keyAxis->pixelToCoord(keyAxis->coordToPixel(keyAxis->range().lower)-strokeMargin*((keyAxis->orientation()==Qt::Vertical)!=keyAxis->rangeReversed()?-1:1));
17718 double rectRight = keyAxis->pixelToCoord(keyAxis->coordToPixel(keyAxis->range().upper)+strokeMargin*((keyAxis->orientation()==Qt::Vertical)!=keyAxis->rangeReversed()?-1:1));
17219 double rectRight = keyAxis->pixelToCoord(keyAxis->coordToPixel(keyAxis->range().upper)+strokeMargin*((keyAxis->orientation()==Qt::Vertical)!=keyAxis->rangeReversed()?-1:1));
17719 double rectBottom = valueAxis->pixelToCoord(valueAxis->coordToPixel(valueAxis->range().lower)+strokeMargin*((valueAxis->orientation()==Qt::Horizontal)!=valueAxis->rangeReversed()?-1:1));
17220 double rectBottom = valueAxis->pixelToCoord(valueAxis->coordToPixel(valueAxis->range().lower)+strokeMargin*((valueAxis->orientation()==Qt::Horizontal)!=valueAxis->rangeReversed()?-1:1));
17720 double rectTop = valueAxis->pixelToCoord(valueAxis->coordToPixel(valueAxis->range().upper)-strokeMargin*((valueAxis->orientation()==Qt::Horizontal)!=valueAxis->rangeReversed()?-1:1));
17221 double rectTop = valueAxis->pixelToCoord(valueAxis->coordToPixel(valueAxis->range().upper)-strokeMargin*((valueAxis->orientation()==Qt::Horizontal)!=valueAxis->rangeReversed()?-1:1));
17721 int currentRegion;
17222 int currentRegion;
17722 QCPCurveDataMap::const_iterator it = mData->constBegin();
17223 QCPCurveDataMap::const_iterator it = mData->constBegin();
17723 QCPCurveDataMap::const_iterator prevIt = mData->constEnd()-1;
17224 QCPCurveDataMap::const_iterator prevIt = mData->constEnd()-1;
17724 int prevRegion = getRegion(prevIt.value().key, prevIt.value().value, rectLeft, rectTop, rectRight, rectBottom);
17225 int prevRegion = getRegion(prevIt.value().key, prevIt.value().value, rectLeft, rectTop, rectRight, rectBottom);
17725 QVector<QPointF> trailingPoints; // points that must be applied after all other points (are generated only when handling first point to get virtual segment between last and first point right)
17226 QVector<QPointF> trailingPoints; // points that must be applied after all other points (are generated only when handling first point to get virtual segment between last and first point right)
17726 while (it != mData->constEnd())
17227 while (it != mData->constEnd())
17727 {
17228 {
17728 currentRegion = getRegion(it.value().key, it.value().value, rectLeft, rectTop, rectRight, rectBottom);
17229 currentRegion = getRegion(it.value().key, it.value().value, rectLeft, rectTop, rectRight, rectBottom);
17729 if (currentRegion != prevRegion) // changed region, possibly need to add some optimized edge points or original points if entering R
17230 if (currentRegion != prevRegion) // changed region, possibly need to add some optimized edge points or original points if entering R
17730 {
17231 {
17731 if (currentRegion != 5) // segment doesn't end in R, so it's a candidate for removal
17232 if (currentRegion != 5) // segment doesn't end in R, so it's a candidate for removal
17732 {
17233 {
17733 QPointF crossA, crossB;
17234 QPointF crossA, crossB;
17734 if (prevRegion == 5) // we're coming from R, so add this point optimized
17235 if (prevRegion == 5) // we're coming from R, so add this point optimized
17735 {
17236 {
17736 lineData->append(getOptimizedPoint(currentRegion, it.value().key, it.value().value, prevIt.value().key, prevIt.value().value, rectLeft, rectTop, rectRight, rectBottom));
17237 lineData->append(getOptimizedPoint(currentRegion, it.value().key, it.value().value, prevIt.value().key, prevIt.value().value, rectLeft, rectTop, rectRight, rectBottom));
17737 // in the situations 5->1/7/9/3 the segment may leave R and directly cross through two outer regions. In these cases we need to add an additional corner point
17238 // in the situations 5->1/7/9/3 the segment may leave R and directly cross through two outer regions. In these cases we need to add an additional corner point
17738 *lineData << getOptimizedCornerPoints(prevRegion, currentRegion, prevIt.value().key, prevIt.value().value, it.value().key, it.value().value, rectLeft, rectTop, rectRight, rectBottom);
17239 *lineData << getOptimizedCornerPoints(prevRegion, currentRegion, prevIt.value().key, prevIt.value().value, it.value().key, it.value().value, rectLeft, rectTop, rectRight, rectBottom);
17739 } else if (mayTraverse(prevRegion, currentRegion) &&
17240 } else if (mayTraverse(prevRegion, currentRegion) &&
17740 getTraverse(prevIt.value().key, prevIt.value().value, it.value().key, it.value().value, rectLeft, rectTop, rectRight, rectBottom, crossA, crossB))
17241 getTraverse(prevIt.value().key, prevIt.value().value, it.value().key, it.value().value, rectLeft, rectTop, rectRight, rectBottom, crossA, crossB))
17741 {
17242 {
17742 // add the two cross points optimized if segment crosses R and if segment isn't virtual zeroth segment between last and first curve point:
17243 // add the two cross points optimized if segment crosses R and if segment isn't virtual zeroth segment between last and first curve point:
17743 QVector<QPointF> beforeTraverseCornerPoints, afterTraverseCornerPoints;
17244 QVector<QPointF> beforeTraverseCornerPoints, afterTraverseCornerPoints;
17744 getTraverseCornerPoints(prevRegion, currentRegion, rectLeft, rectTop, rectRight, rectBottom, beforeTraverseCornerPoints, afterTraverseCornerPoints);
17245 getTraverseCornerPoints(prevRegion, currentRegion, rectLeft, rectTop, rectRight, rectBottom, beforeTraverseCornerPoints, afterTraverseCornerPoints);
17745 if (it != mData->constBegin())
17246 if (it != mData->constBegin())
17746 {
17247 {
17747 *lineData << beforeTraverseCornerPoints;
17248 *lineData << beforeTraverseCornerPoints;
17748 lineData->append(crossA);
17249 lineData->append(crossA);
17749 lineData->append(crossB);
17250 lineData->append(crossB);
17750 *lineData << afterTraverseCornerPoints;
17251 *lineData << afterTraverseCornerPoints;
17751 } else
17252 } else
17752 {
17253 {
17753 lineData->append(crossB);
17254 lineData->append(crossB);
17754 *lineData << afterTraverseCornerPoints;
17255 *lineData << afterTraverseCornerPoints;
17755 trailingPoints << beforeTraverseCornerPoints << crossA ;
17256 trailingPoints << beforeTraverseCornerPoints << crossA ;
17756 }
17257 }
17757 } else // doesn't cross R, line is just moving around in outside regions, so only need to add optimized point(s) at the boundary corner(s)
17258 } else // doesn't cross R, line is just moving around in outside regions, so only need to add optimized point(s) at the boundary corner(s)
17758 {
17259 {
17759 *lineData << getOptimizedCornerPoints(prevRegion, currentRegion, prevIt.value().key, prevIt.value().value, it.value().key, it.value().value, rectLeft, rectTop, rectRight, rectBottom);
17260 *lineData << getOptimizedCornerPoints(prevRegion, currentRegion, prevIt.value().key, prevIt.value().value, it.value().key, it.value().value, rectLeft, rectTop, rectRight, rectBottom);
17760 }
17261 }
17761 } else // segment does end in R, so we add previous point optimized and this point at original position
17262 } else // segment does end in R, so we add previous point optimized and this point at original position
17762 {
17263 {
17763 if (it == mData->constBegin()) // it is first point in curve and prevIt is last one. So save optimized point for adding it to the lineData in the end
17264 if (it == mData->constBegin()) // it is first point in curve and prevIt is last one. So save optimized point for adding it to the lineData in the end
17764 trailingPoints << getOptimizedPoint(prevRegion, prevIt.value().key, prevIt.value().value, it.value().key, it.value().value, rectLeft, rectTop, rectRight, rectBottom);
17265 trailingPoints << getOptimizedPoint(prevRegion, prevIt.value().key, prevIt.value().value, it.value().key, it.value().value, rectLeft, rectTop, rectRight, rectBottom);
17765 else
17266 else
17766 lineData->append(getOptimizedPoint(prevRegion, prevIt.value().key, prevIt.value().value, it.value().key, it.value().value, rectLeft, rectTop, rectRight, rectBottom));
17267 lineData->append(getOptimizedPoint(prevRegion, prevIt.value().key, prevIt.value().value, it.value().key, it.value().value, rectLeft, rectTop, rectRight, rectBottom));
17767 lineData->append(coordsToPixels(it.value().key, it.value().value));
17268 lineData->append(coordsToPixels(it.value().key, it.value().value));
17768 }
17269 }
17769 } else // region didn't change
17270 } else // region didn't change
17770 {
17271 {
17771 if (currentRegion == 5) // still in R, keep adding original points
17272 if (currentRegion == 5) // still in R, keep adding original points
17772 {
17273 {
17773 lineData->append(coordsToPixels(it.value().key, it.value().value));
17274 lineData->append(coordsToPixels(it.value().key, it.value().value));
17774 } else // still outside R, no need to add anything
17275 } else // still outside R, no need to add anything
17775 {
17276 {
17776 // see how this is not doing anything? That's the main optimization...
17277 // see how this is not doing anything? That's the main optimization...
17777 }
17278 }
17778 }
17279 }
17779 prevIt = it;
17280 prevIt = it;
17780 prevRegion = currentRegion;
17281 prevRegion = currentRegion;
17781 ++it;
17282 ++it;
17782 }
17283 }
17783 *lineData << trailingPoints;
17284 *lineData << trailingPoints;
17784 }
17285 }
17785
17286
17786 /*! \internal
17287 /*! \internal
@@ -17803,30 +17304,30 void QCPCurve::getCurveData(QVector<QPoi
17803 */
17304 */
17804 int QCPCurve::getRegion(double x, double y, double rectLeft, double rectTop, double rectRight, double rectBottom) const
17305 int QCPCurve::getRegion(double x, double y, double rectLeft, double rectTop, double rectRight, double rectBottom) const
17805 {
17306 {
17806 if (x < rectLeft) // region 123
17307 if (x < rectLeft) // region 123
17807 {
17308 {
17808 if (y > rectTop)
17309 if (y > rectTop)
17809 return 1;
17310 return 1;
17810 else if (y < rectBottom)
17311 else if (y < rectBottom)
17811 return 3;
17312 return 3;
17812 else
17313 else
17813 return 2;
17314 return 2;
17814 } else if (x > rectRight) // region 789
17315 } else if (x > rectRight) // region 789
17815 {
17316 {
17816 if (y > rectTop)
17317 if (y > rectTop)
17817 return 7;
17318 return 7;
17818 else if (y < rectBottom)
17319 else if (y < rectBottom)
17819 return 9;
17320 return 9;
17820 else
17321 else
17821 return 8;
17322 return 8;
17822 } else // region 456
17323 } else // region 456
17823 {
17324 {
17824 if (y > rectTop)
17325 if (y > rectTop)
17825 return 4;
17326 return 4;
17826 else if (y < rectBottom)
17327 else if (y < rectBottom)
17827 return 6;
17328 return 6;
17828 else
17329 else
17829 return 5;
17330 return 5;
17830 }
17331 }
17831 }
17332 }
17832
17333
@@ -17847,84 +17348,84 int QCPCurve::getRegion(double x, double
17847 */
17348 */
17848 QPointF QCPCurve::getOptimizedPoint(int otherRegion, double otherKey, double otherValue, double key, double value, double rectLeft, double rectTop, double rectRight, double rectBottom) const
17349 QPointF QCPCurve::getOptimizedPoint(int otherRegion, double otherKey, double otherValue, double key, double value, double rectLeft, double rectTop, double rectRight, double rectBottom) const
17849 {
17350 {
17850 double intersectKey = rectLeft; // initial value is just fail-safe
17351 double intersectKey = rectLeft; // initial value is just fail-safe
17851 double intersectValue = rectTop; // initial value is just fail-safe
17352 double intersectValue = rectTop; // initial value is just fail-safe
17852 switch (otherRegion)
17353 switch (otherRegion)
17853 {
17354 {
17854 case 1: // top and left edge
17355 case 1: // top and left edge
17855 {
17356 {
17856 intersectValue = rectTop;
17357 intersectValue = rectTop;
17857 intersectKey = otherKey + (key-otherKey)/(value-otherValue)*(intersectValue-otherValue);
17358 intersectKey = otherKey + (key-otherKey)/(value-otherValue)*(intersectValue-otherValue);
17858 if (intersectKey < rectLeft || intersectKey > rectRight) // doesn't intersect, so must intersect other:
17359 if (intersectKey < rectLeft || intersectKey > rectRight) // doesn't intersect, so must intersect other:
17859 {
17360 {
17860 intersectKey = rectLeft;
17361 intersectKey = rectLeft;
17861 intersectValue = otherValue + (value-otherValue)/(key-otherKey)*(intersectKey-otherKey);
17362 intersectValue = otherValue + (value-otherValue)/(key-otherKey)*(intersectKey-otherKey);
17862 }
17363 }
17863 break;
17364 break;
17864 }
17365 }
17865 case 2: // left edge
17366 case 2: // left edge
17866 {
17367 {
17867 intersectKey = rectLeft;
17368 intersectKey = rectLeft;
17868 intersectValue = otherValue + (value-otherValue)/(key-otherKey)*(intersectKey-otherKey);
17369 intersectValue = otherValue + (value-otherValue)/(key-otherKey)*(intersectKey-otherKey);
17869 break;
17370 break;
17870 }
17371 }
17871 case 3: // bottom and left edge
17372 case 3: // bottom and left edge
17872 {
17373 {
17873 intersectValue = rectBottom;
17374 intersectValue = rectBottom;
17874 intersectKey = otherKey + (key-otherKey)/(value-otherValue)*(intersectValue-otherValue);
17375 intersectKey = otherKey + (key-otherKey)/(value-otherValue)*(intersectValue-otherValue);
17875 if (intersectKey < rectLeft || intersectKey > rectRight) // doesn't intersect, so must intersect other:
17376 if (intersectKey < rectLeft || intersectKey > rectRight) // doesn't intersect, so must intersect other:
17876 {
17377 {
17877 intersectKey = rectLeft;
17378 intersectKey = rectLeft;
17878 intersectValue = otherValue + (value-otherValue)/(key-otherKey)*(intersectKey-otherKey);
17379 intersectValue = otherValue + (value-otherValue)/(key-otherKey)*(intersectKey-otherKey);
17879 }
17380 }
17880 break;
17381 break;
17881 }
17382 }
17882 case 4: // top edge
17383 case 4: // top edge
17883 {
17384 {
17884 intersectValue = rectTop;
17385 intersectValue = rectTop;
17885 intersectKey = otherKey + (key-otherKey)/(value-otherValue)*(intersectValue-otherValue);
17386 intersectKey = otherKey + (key-otherKey)/(value-otherValue)*(intersectValue-otherValue);
17886 break;
17387 break;
17887 }
17388 }
17888 case 5:
17389 case 5:
17889 {
17390 {
17890 break; // case 5 shouldn't happen for this function but we add it anyway to prevent potential discontinuity in branch table
17391 break; // case 5 shouldn't happen for this function but we add it anyway to prevent potential discontinuity in branch table
17891 }
17392 }
17892 case 6: // bottom edge
17393 case 6: // bottom edge
17893 {
17394 {
17894 intersectValue = rectBottom;
17395 intersectValue = rectBottom;
17895 intersectKey = otherKey + (key-otherKey)/(value-otherValue)*(intersectValue-otherValue);
17396 intersectKey = otherKey + (key-otherKey)/(value-otherValue)*(intersectValue-otherValue);
17896 break;
17397 break;
17897 }
17398 }
17898 case 7: // top and right edge
17399 case 7: // top and right edge
17899 {
17400 {
17900 intersectValue = rectTop;
17401 intersectValue = rectTop;
17901 intersectKey = otherKey + (key-otherKey)/(value-otherValue)*(intersectValue-otherValue);
17402 intersectKey = otherKey + (key-otherKey)/(value-otherValue)*(intersectValue-otherValue);
17902 if (intersectKey < rectLeft || intersectKey > rectRight) // doesn't intersect, so must intersect other:
17403 if (intersectKey < rectLeft || intersectKey > rectRight) // doesn't intersect, so must intersect other:
17903 {
17404 {
17904 intersectKey = rectRight;
17405 intersectKey = rectRight;
17905 intersectValue = otherValue + (value-otherValue)/(key-otherKey)*(intersectKey-otherKey);
17406 intersectValue = otherValue + (value-otherValue)/(key-otherKey)*(intersectKey-otherKey);
17906 }
17407 }
17907 break;
17408 break;
17908 }
17409 }
17909 case 8: // right edge
17410 case 8: // right edge
17910 {
17411 {
17911 intersectKey = rectRight;
17412 intersectKey = rectRight;
17912 intersectValue = otherValue + (value-otherValue)/(key-otherKey)*(intersectKey-otherKey);
17413 intersectValue = otherValue + (value-otherValue)/(key-otherKey)*(intersectKey-otherKey);
17913 break;
17414 break;
17914 }
17415 }
17915 case 9: // bottom and right edge
17416 case 9: // bottom and right edge
17916 {
17417 {
17917 intersectValue = rectBottom;
17418 intersectValue = rectBottom;
17918 intersectKey = otherKey + (key-otherKey)/(value-otherValue)*(intersectValue-otherValue);
17419 intersectKey = otherKey + (key-otherKey)/(value-otherValue)*(intersectValue-otherValue);
17919 if (intersectKey < rectLeft || intersectKey > rectRight) // doesn't intersect, so must intersect other:
17420 if (intersectKey < rectLeft || intersectKey > rectRight) // doesn't intersect, so must intersect other:
17920 {
17421 {
17921 intersectKey = rectRight;
17422 intersectKey = rectRight;
17922 intersectValue = otherValue + (value-otherValue)/(key-otherKey)*(intersectKey-otherKey);
17423 intersectValue = otherValue + (value-otherValue)/(key-otherKey)*(intersectKey-otherKey);
17923 }
17424 }
17924 break;
17425 break;
17925 }
17426 }
17926 }
17427 }
17927 return coordsToPixels(intersectKey, intersectValue);
17428 return coordsToPixels(intersectKey, intersectValue);
17928 }
17429 }
17929
17430
17930 /*! \internal
17431 /*! \internal
@@ -17947,154 +17448,154 QPointF QCPCurve::getOptimizedPoint(int
17947 */
17448 */
17948 QVector<QPointF> QCPCurve::getOptimizedCornerPoints(int prevRegion, int currentRegion, double prevKey, double prevValue, double key, double value, double rectLeft, double rectTop, double rectRight, double rectBottom) const
17449 QVector<QPointF> QCPCurve::getOptimizedCornerPoints(int prevRegion, int currentRegion, double prevKey, double prevValue, double key, double value, double rectLeft, double rectTop, double rectRight, double rectBottom) const
17949 {
17450 {
17950 QVector<QPointF> result;
17451 QVector<QPointF> result;
17951 switch (prevRegion)
17452 switch (prevRegion)
17952 {
17453 {
17953 case 1:
17454 case 1:
17954 {
17455 {
17955 switch (currentRegion)
17456 switch (currentRegion)
17956 {
17457 {
17957 case 2: { result << coordsToPixels(rectLeft, rectTop); break; }
17458 case 2: { result << coordsToPixels(rectLeft, rectTop); break; }
17958 case 4: { result << coordsToPixels(rectLeft, rectTop); break; }
17459 case 4: { result << coordsToPixels(rectLeft, rectTop); break; }
17959 case 3: { result << coordsToPixels(rectLeft, rectTop) << coordsToPixels(rectLeft, rectBottom); break; }
17460 case 3: { result << coordsToPixels(rectLeft, rectTop) << coordsToPixels(rectLeft, rectBottom); break; }
17960 case 7: { result << coordsToPixels(rectLeft, rectTop) << coordsToPixels(rectRight, rectTop); break; }
17461 case 7: { result << coordsToPixels(rectLeft, rectTop) << coordsToPixels(rectRight, rectTop); break; }
17961 case 6: { result << coordsToPixels(rectLeft, rectTop) << coordsToPixels(rectLeft, rectBottom); result.append(result.last()); break; }
17462 case 6: { result << coordsToPixels(rectLeft, rectTop) << coordsToPixels(rectLeft, rectBottom); result.append(result.last()); break; }
17962 case 8: { result << coordsToPixels(rectLeft, rectTop) << coordsToPixels(rectRight, rectTop); result.append(result.last()); break; }
17463 case 8: { result << coordsToPixels(rectLeft, rectTop) << coordsToPixels(rectRight, rectTop); result.append(result.last()); break; }
17963 case 9: { // in this case we need another distinction of cases: segment may pass below or above rect, requiring either bottom right or top left corner points
17464 case 9: { // in this case we need another distinction of cases: segment may pass below or above rect, requiring either bottom right or top left corner points
17964 if ((value-prevValue)/(key-prevKey)*(rectLeft-key)+value < rectBottom) // segment passes below R
17465 if ((value-prevValue)/(key-prevKey)*(rectLeft-key)+value < rectBottom) // segment passes below R
17965 { result << coordsToPixels(rectLeft, rectTop) << coordsToPixels(rectLeft, rectBottom); result.append(result.last()); result << coordsToPixels(rectRight, rectBottom); }
17466 { result << coordsToPixels(rectLeft, rectTop) << coordsToPixels(rectLeft, rectBottom); result.append(result.last()); result << coordsToPixels(rectRight, rectBottom); }
17966 else
17467 else
17967 { result << coordsToPixels(rectLeft, rectTop) << coordsToPixels(rectRight, rectTop); result.append(result.last()); result << coordsToPixels(rectRight, rectBottom); }
17468 { result << coordsToPixels(rectLeft, rectTop) << coordsToPixels(rectRight, rectTop); result.append(result.last()); result << coordsToPixels(rectRight, rectBottom); }
17968 break;
17469 break;
17969 }
17470 }
17970 }
17471 }
17971 break;
17472 break;
17972 }
17473 }
17973 case 2:
17474 case 2:
17974 {
17475 {
17975 switch (currentRegion)
17476 switch (currentRegion)
17976 {
17477 {
17977 case 1: { result << coordsToPixels(rectLeft, rectTop); break; }
17478 case 1: { result << coordsToPixels(rectLeft, rectTop); break; }
17978 case 3: { result << coordsToPixels(rectLeft, rectBottom); break; }
17479 case 3: { result << coordsToPixels(rectLeft, rectBottom); break; }
17979 case 4: { result << coordsToPixels(rectLeft, rectTop); result.append(result.last()); break; }
17480 case 4: { result << coordsToPixels(rectLeft, rectTop); result.append(result.last()); break; }
17980 case 6: { result << coordsToPixels(rectLeft, rectBottom); result.append(result.last()); break; }
17481 case 6: { result << coordsToPixels(rectLeft, rectBottom); result.append(result.last()); break; }
17981 case 7: { result << coordsToPixels(rectLeft, rectTop); result.append(result.last()); result << coordsToPixels(rectRight, rectTop); break; }
17482 case 7: { result << coordsToPixels(rectLeft, rectTop); result.append(result.last()); result << coordsToPixels(rectRight, rectTop); break; }
17982 case 9: { result << coordsToPixels(rectLeft, rectBottom); result.append(result.last()); result << coordsToPixels(rectRight, rectBottom); break; }
17483 case 9: { result << coordsToPixels(rectLeft, rectBottom); result.append(result.last()); result << coordsToPixels(rectRight, rectBottom); break; }
17983 }
17484 }
17984 break;
17485 break;
17985 }
17486 }
17986 case 3:
17487 case 3:
17987 {
17488 {
17988 switch (currentRegion)
17489 switch (currentRegion)
17989 {
17490 {
17990 case 2: { result << coordsToPixels(rectLeft, rectBottom); break; }
17491 case 2: { result << coordsToPixels(rectLeft, rectBottom); break; }
17991 case 6: { result << coordsToPixels(rectLeft, rectBottom); break; }
17492 case 6: { result << coordsToPixels(rectLeft, rectBottom); break; }
17992 case 1: { result << coordsToPixels(rectLeft, rectBottom) << coordsToPixels(rectLeft, rectTop); break; }
17493 case 1: { result << coordsToPixels(rectLeft, rectBottom) << coordsToPixels(rectLeft, rectTop); break; }
17993 case 9: { result << coordsToPixels(rectLeft, rectBottom) << coordsToPixels(rectRight, rectBottom); break; }
17494 case 9: { result << coordsToPixels(rectLeft, rectBottom) << coordsToPixels(rectRight, rectBottom); break; }
17994 case 4: { result << coordsToPixels(rectLeft, rectBottom) << coordsToPixels(rectLeft, rectTop); result.append(result.last()); break; }
17495 case 4: { result << coordsToPixels(rectLeft, rectBottom) << coordsToPixels(rectLeft, rectTop); result.append(result.last()); break; }
17995 case 8: { result << coordsToPixels(rectLeft, rectBottom) << coordsToPixels(rectRight, rectBottom); result.append(result.last()); break; }
17496 case 8: { result << coordsToPixels(rectLeft, rectBottom) << coordsToPixels(rectRight, rectBottom); result.append(result.last()); break; }
17996 case 7: { // in this case we need another distinction of cases: segment may pass below or above rect, requiring either bottom right or top left corner points
17497 case 7: { // in this case we need another distinction of cases: segment may pass below or above rect, requiring either bottom right or top left corner points
17997 if ((value-prevValue)/(key-prevKey)*(rectRight-key)+value < rectBottom) // segment passes below R
17498 if ((value-prevValue)/(key-prevKey)*(rectRight-key)+value < rectBottom) // segment passes below R
17998 { result << coordsToPixels(rectLeft, rectBottom) << coordsToPixels(rectRight, rectBottom); result.append(result.last()); result << coordsToPixels(rectRight, rectTop); }
17499 { result << coordsToPixels(rectLeft, rectBottom) << coordsToPixels(rectRight, rectBottom); result.append(result.last()); result << coordsToPixels(rectRight, rectTop); }
17999 else
17500 else
18000 { result << coordsToPixels(rectLeft, rectBottom) << coordsToPixels(rectLeft, rectTop); result.append(result.last()); result << coordsToPixels(rectRight, rectTop); }
17501 { result << coordsToPixels(rectLeft, rectBottom) << coordsToPixels(rectLeft, rectTop); result.append(result.last()); result << coordsToPixels(rectRight, rectTop); }
18001 break;
17502 break;
18002 }
17503 }
18003 }
17504 }
18004 break;
17505 break;
18005 }
17506 }
18006 case 4:
17507 case 4:
18007 {
17508 {
18008 switch (currentRegion)
17509 switch (currentRegion)
18009 {
17510 {
18010 case 1: { result << coordsToPixels(rectLeft, rectTop); break; }
17511 case 1: { result << coordsToPixels(rectLeft, rectTop); break; }
18011 case 7: { result << coordsToPixels(rectRight, rectTop); break; }
17512 case 7: { result << coordsToPixels(rectRight, rectTop); break; }
18012 case 2: { result << coordsToPixels(rectLeft, rectTop); result.append(result.last()); break; }
17513 case 2: { result << coordsToPixels(rectLeft, rectTop); result.append(result.last()); break; }
18013 case 8: { result << coordsToPixels(rectRight, rectTop); result.append(result.last()); break; }
17514 case 8: { result << coordsToPixels(rectRight, rectTop); result.append(result.last()); break; }
18014 case 3: { result << coordsToPixels(rectLeft, rectTop); result.append(result.last()); result << coordsToPixels(rectLeft, rectBottom); break; }
17515 case 3: { result << coordsToPixels(rectLeft, rectTop); result.append(result.last()); result << coordsToPixels(rectLeft, rectBottom); break; }
18015 case 9: { result << coordsToPixels(rectRight, rectTop); result.append(result.last()); result << coordsToPixels(rectRight, rectBottom); break; }
17516 case 9: { result << coordsToPixels(rectRight, rectTop); result.append(result.last()); result << coordsToPixels(rectRight, rectBottom); break; }
18016 }
17517 }
18017 break;
17518 break;
18018 }
17519 }
18019 case 5:
17520 case 5:
18020 {
17521 {
18021 switch (currentRegion)
17522 switch (currentRegion)
18022 {
17523 {
18023 case 1: { result << coordsToPixels(rectLeft, rectTop); break; }
17524 case 1: { result << coordsToPixels(rectLeft, rectTop); break; }
18024 case 7: { result << coordsToPixels(rectRight, rectTop); break; }
17525 case 7: { result << coordsToPixels(rectRight, rectTop); break; }
18025 case 9: { result << coordsToPixels(rectRight, rectBottom); break; }
17526 case 9: { result << coordsToPixels(rectRight, rectBottom); break; }
18026 case 3: { result << coordsToPixels(rectLeft, rectBottom); break; }
17527 case 3: { result << coordsToPixels(rectLeft, rectBottom); break; }
18027 }
17528 }
18028 break;
17529 break;
18029 }
17530 }
18030 case 6:
17531 case 6:
18031 {
17532 {
18032 switch (currentRegion)
17533 switch (currentRegion)
18033 {
17534 {
18034 case 3: { result << coordsToPixels(rectLeft, rectBottom); break; }
17535 case 3: { result << coordsToPixels(rectLeft, rectBottom); break; }
18035 case 9: { result << coordsToPixels(rectRight, rectBottom); break; }
17536 case 9: { result << coordsToPixels(rectRight, rectBottom); break; }
18036 case 2: { result << coordsToPixels(rectLeft, rectBottom); result.append(result.last()); break; }
17537 case 2: { result << coordsToPixels(rectLeft, rectBottom); result.append(result.last()); break; }
18037 case 8: { result << coordsToPixels(rectRight, rectBottom); result.append(result.last()); break; }
17538 case 8: { result << coordsToPixels(rectRight, rectBottom); result.append(result.last()); break; }
18038 case 1: { result << coordsToPixels(rectLeft, rectBottom); result.append(result.last()); result << coordsToPixels(rectLeft, rectTop); break; }
17539 case 1: { result << coordsToPixels(rectLeft, rectBottom); result.append(result.last()); result << coordsToPixels(rectLeft, rectTop); break; }
18039 case 7: { result << coordsToPixels(rectRight, rectBottom); result.append(result.last()); result << coordsToPixels(rectRight, rectTop); break; }
17540 case 7: { result << coordsToPixels(rectRight, rectBottom); result.append(result.last()); result << coordsToPixels(rectRight, rectTop); break; }
18040 }
17541 }
18041 break;
17542 break;
18042 }
17543 }
18043 case 7:
17544 case 7:
18044 {
17545 {
18045 switch (currentRegion)
17546 switch (currentRegion)
18046 {
17547 {
18047 case 4: { result << coordsToPixels(rectRight, rectTop); break; }
17548 case 4: { result << coordsToPixels(rectRight, rectTop); break; }
18048 case 8: { result << coordsToPixels(rectRight, rectTop); break; }
17549 case 8: { result << coordsToPixels(rectRight, rectTop); break; }
18049 case 1: { result << coordsToPixels(rectRight, rectTop) << coordsToPixels(rectLeft, rectTop); break; }
17550 case 1: { result << coordsToPixels(rectRight, rectTop) << coordsToPixels(rectLeft, rectTop); break; }
18050 case 9: { result << coordsToPixels(rectRight, rectTop) << coordsToPixels(rectRight, rectBottom); break; }
17551 case 9: { result << coordsToPixels(rectRight, rectTop) << coordsToPixels(rectRight, rectBottom); break; }
18051 case 2: { result << coordsToPixels(rectRight, rectTop) << coordsToPixels(rectLeft, rectTop); result.append(result.last()); break; }
17552 case 2: { result << coordsToPixels(rectRight, rectTop) << coordsToPixels(rectLeft, rectTop); result.append(result.last()); break; }
18052 case 6: { result << coordsToPixels(rectRight, rectTop) << coordsToPixels(rectRight, rectBottom); result.append(result.last()); break; }
17553 case 6: { result << coordsToPixels(rectRight, rectTop) << coordsToPixels(rectRight, rectBottom); result.append(result.last()); break; }
18053 case 3: { // in this case we need another distinction of cases: segment may pass below or above rect, requiring either bottom right or top left corner points
17554 case 3: { // in this case we need another distinction of cases: segment may pass below or above rect, requiring either bottom right or top left corner points
18054 if ((value-prevValue)/(key-prevKey)*(rectRight-key)+value < rectBottom) // segment passes below R
17555 if ((value-prevValue)/(key-prevKey)*(rectRight-key)+value < rectBottom) // segment passes below R
18055 { result << coordsToPixels(rectRight, rectTop) << coordsToPixels(rectRight, rectBottom); result.append(result.last()); result << coordsToPixels(rectLeft, rectBottom); }
17556 { result << coordsToPixels(rectRight, rectTop) << coordsToPixels(rectRight, rectBottom); result.append(result.last()); result << coordsToPixels(rectLeft, rectBottom); }
18056 else
17557 else
18057 { result << coordsToPixels(rectRight, rectTop) << coordsToPixels(rectLeft, rectTop); result.append(result.last()); result << coordsToPixels(rectLeft, rectBottom); }
17558 { result << coordsToPixels(rectRight, rectTop) << coordsToPixels(rectLeft, rectTop); result.append(result.last()); result << coordsToPixels(rectLeft, rectBottom); }
18058 break;
17559 break;
18059 }
17560 }
18060 }
17561 }
18061 break;
17562 break;
18062 }
17563 }
18063 case 8:
17564 case 8:
18064 {
17565 {
18065 switch (currentRegion)
17566 switch (currentRegion)
18066 {
17567 {
18067 case 7: { result << coordsToPixels(rectRight, rectTop); break; }
17568 case 7: { result << coordsToPixels(rectRight, rectTop); break; }
18068 case 9: { result << coordsToPixels(rectRight, rectBottom); break; }
17569 case 9: { result << coordsToPixels(rectRight, rectBottom); break; }
18069 case 4: { result << coordsToPixels(rectRight, rectTop); result.append(result.last()); break; }
17570 case 4: { result << coordsToPixels(rectRight, rectTop); result.append(result.last()); break; }
18070 case 6: { result << coordsToPixels(rectRight, rectBottom); result.append(result.last()); break; }
17571 case 6: { result << coordsToPixels(rectRight, rectBottom); result.append(result.last()); break; }
18071 case 1: { result << coordsToPixels(rectRight, rectTop); result.append(result.last()); result << coordsToPixels(rectLeft, rectTop); break; }
17572 case 1: { result << coordsToPixels(rectRight, rectTop); result.append(result.last()); result << coordsToPixels(rectLeft, rectTop); break; }
18072 case 3: { result << coordsToPixels(rectRight, rectBottom); result.append(result.last()); result << coordsToPixels(rectLeft, rectBottom); break; }
17573 case 3: { result << coordsToPixels(rectRight, rectBottom); result.append(result.last()); result << coordsToPixels(rectLeft, rectBottom); break; }
18073 }
17574 }
18074 break;
17575 break;
18075 }
17576 }
18076 case 9:
17577 case 9:
18077 {
17578 {
18078 switch (currentRegion)
17579 switch (currentRegion)
18079 {
17580 {
18080 case 6: { result << coordsToPixels(rectRight, rectBottom); break; }
17581 case 6: { result << coordsToPixels(rectRight, rectBottom); break; }
18081 case 8: { result << coordsToPixels(rectRight, rectBottom); break; }
17582 case 8: { result << coordsToPixels(rectRight, rectBottom); break; }
18082 case 3: { result << coordsToPixels(rectRight, rectBottom) << coordsToPixels(rectLeft, rectBottom); break; }
17583 case 3: { result << coordsToPixels(rectRight, rectBottom) << coordsToPixels(rectLeft, rectBottom); break; }
18083 case 7: { result << coordsToPixels(rectRight, rectBottom) << coordsToPixels(rectRight, rectTop); break; }
17584 case 7: { result << coordsToPixels(rectRight, rectBottom) << coordsToPixels(rectRight, rectTop); break; }
18084 case 2: { result << coordsToPixels(rectRight, rectBottom) << coordsToPixels(rectLeft, rectBottom); result.append(result.last()); break; }
17585 case 2: { result << coordsToPixels(rectRight, rectBottom) << coordsToPixels(rectLeft, rectBottom); result.append(result.last()); break; }
18085 case 4: { result << coordsToPixels(rectRight, rectBottom) << coordsToPixels(rectRight, rectTop); result.append(result.last()); break; }
17586 case 4: { result << coordsToPixels(rectRight, rectBottom) << coordsToPixels(rectRight, rectTop); result.append(result.last()); break; }
18086 case 1: { // in this case we need another distinction of cases: segment may pass below or above rect, requiring either bottom right or top left corner points
17587 case 1: { // in this case we need another distinction of cases: segment may pass below or above rect, requiring either bottom right or top left corner points
18087 if ((value-prevValue)/(key-prevKey)*(rectLeft-key)+value < rectBottom) // segment passes below R
17588 if ((value-prevValue)/(key-prevKey)*(rectLeft-key)+value < rectBottom) // segment passes below R
18088 { result << coordsToPixels(rectRight, rectBottom) << coordsToPixels(rectLeft, rectBottom); result.append(result.last()); result << coordsToPixels(rectLeft, rectTop); }
17589 { result << coordsToPixels(rectRight, rectBottom) << coordsToPixels(rectLeft, rectBottom); result.append(result.last()); result << coordsToPixels(rectLeft, rectTop); }
18089 else
17590 else
18090 { result << coordsToPixels(rectRight, rectBottom) << coordsToPixels(rectRight, rectTop); result.append(result.last()); result << coordsToPixels(rectLeft, rectTop); }
17591 { result << coordsToPixels(rectRight, rectBottom) << coordsToPixels(rectRight, rectTop); result.append(result.last()); result << coordsToPixels(rectLeft, rectTop); }
18091 break;
17592 break;
18092 }
17593 }
18093 }
17594 }
18094 break;
17595 break;
18095 }
17596 }
18096 }
17597 }
18097 return result;
17598 return result;
18098 }
17599 }
18099
17600
18100 /*! \internal
17601 /*! \internal
@@ -18111,89 +17612,89 QVector<QPointF> QCPCurve::getOptimizedC
18111 */
17612 */
18112 bool QCPCurve::mayTraverse(int prevRegion, int currentRegion) const
17613 bool QCPCurve::mayTraverse(int prevRegion, int currentRegion) const
18113 {
17614 {
18114 switch (prevRegion)
17615 switch (prevRegion)
18115 {
17616 {
18116 case 1:
17617 case 1:
18117 {
17618 {
18118 switch (currentRegion)
17619 switch (currentRegion)
18119 {
17620 {
18120 case 4:
17621 case 4:
18121 case 7:
17622 case 7:
18122 case 2:
17623 case 2:
18123 case 3: return false;
17624 case 3: return false;
18124 default: return true;
17625 default: return true;
18125 }
17626 }
18126 }
17627 }
18127 case 2:
17628 case 2:
18128 {
17629 {
18129 switch (currentRegion)
17630 switch (currentRegion)
18130 {
17631 {
18131 case 1:
17632 case 1:
18132 case 3: return false;
17633 case 3: return false;
18133 default: return true;
17634 default: return true;
18134 }
17635 }
18135 }
17636 }
18136 case 3:
17637 case 3:
18137 {
17638 {
18138 switch (currentRegion)
17639 switch (currentRegion)
18139 {
17640 {
18140 case 1:
17641 case 1:
18141 case 2:
17642 case 2:
18142 case 6:
17643 case 6:
18143 case 9: return false;
17644 case 9: return false;
18144 default: return true;
17645 default: return true;
18145 }
17646 }
18146 }
17647 }
18147 case 4:
17648 case 4:
18148 {
17649 {
18149 switch (currentRegion)
17650 switch (currentRegion)
18150 {
17651 {
18151 case 1:
17652 case 1:
18152 case 7: return false;
17653 case 7: return false;
18153 default: return true;
17654 default: return true;
18154 }
17655 }
18155 }
17656 }
18156 case 5: return false; // should never occur
17657 case 5: return false; // should never occur
18157 case 6:
17658 case 6:
18158 {
17659 {
18159 switch (currentRegion)
17660 switch (currentRegion)
18160 {
17661 {
18161 case 3:
17662 case 3:
18162 case 9: return false;
17663 case 9: return false;
18163 default: return true;
17664 default: return true;
18164 }
17665 }
18165 }
17666 }
18166 case 7:
17667 case 7:
18167 {
17668 {
18168 switch (currentRegion)
17669 switch (currentRegion)
18169 {
17670 {
18170 case 1:
17671 case 1:
18171 case 4:
17672 case 4:
18172 case 8:
17673 case 8:
18173 case 9: return false;
17674 case 9: return false;
18174 default: return true;
17675 default: return true;
18175 }
17676 }
18176 }
17677 }
18177 case 8:
17678 case 8:
18178 {
17679 {
18179 switch (currentRegion)
17680 switch (currentRegion)
18180 {
17681 {
18181 case 7:
17682 case 7:
18182 case 9: return false;
17683 case 9: return false;
18183 default: return true;
17684 default: return true;
18184 }
17685 }
18185 }
17686 }
18186 case 9:
17687 case 9:
18187 {
17688 {
18188 switch (currentRegion)
17689 switch (currentRegion)
18189 {
17690 {
18190 case 3:
17691 case 3:
18191 case 6:
17692 case 6:
18192 case 8:
17693 case 8:
18193 case 7: return false;
17694 case 7: return false;
18194 default: return true;
17695 default: return true;
18195 }
17696 }
18196 }
17697 }
18197 default: return true;
17698 default: return true;
18198 }
17699 }
18199 }
17700 }
@@ -18214,73 +17715,73 bool QCPCurve::mayTraverse(int prevRegio
18214 */
17715 */
18215 bool QCPCurve::getTraverse(double prevKey, double prevValue, double key, double value, double rectLeft, double rectTop, double rectRight, double rectBottom, QPointF &crossA, QPointF &crossB) const
17716 bool QCPCurve::getTraverse(double prevKey, double prevValue, double key, double value, double rectLeft, double rectTop, double rectRight, double rectBottom, QPointF &crossA, QPointF &crossB) const
18216 {
17717 {
18217 QList<QPointF> intersections; // x of QPointF corresponds to key and y to value
17718 QList<QPointF> intersections; // x of QPointF corresponds to key and y to value
18218 if (qFuzzyIsNull(key-prevKey)) // line is parallel to value axis
17719 if (qFuzzyIsNull(key-prevKey)) // line is parallel to value axis
18219 {
17720 {
18220 // due to region filter in mayTraverseR(), if line is parallel to value or key axis, R is traversed here
17721 // due to region filter in mayTraverseR(), if line is parallel to value or key axis, R is traversed here
18221 intersections.append(QPointF(key, rectBottom)); // direction will be taken care of at end of method
17722 intersections.append(QPointF(key, rectBottom)); // direction will be taken care of at end of method
18222 intersections.append(QPointF(key, rectTop));
17723 intersections.append(QPointF(key, rectTop));
18223 } else if (qFuzzyIsNull(value-prevValue)) // line is parallel to key axis
17724 } else if (qFuzzyIsNull(value-prevValue)) // line is parallel to key axis
18224 {
17725 {
18225 // due to region filter in mayTraverseR(), if line is parallel to value or key axis, R is traversed here
17726 // due to region filter in mayTraverseR(), if line is parallel to value or key axis, R is traversed here
18226 intersections.append(QPointF(rectLeft, value)); // direction will be taken care of at end of method
17727 intersections.append(QPointF(rectLeft, value)); // direction will be taken care of at end of method
18227 intersections.append(QPointF(rectRight, value));
17728 intersections.append(QPointF(rectRight, value));
18228 } else // line is skewed
17729 } else // line is skewed
18229 {
17730 {
18230 double gamma;
17731 double gamma;
18231 double keyPerValue = (key-prevKey)/(value-prevValue);
17732 double keyPerValue = (key-prevKey)/(value-prevValue);
18232 // check top of rect:
17733 // check top of rect:
18233 gamma = prevKey + (rectTop-prevValue)*keyPerValue;
17734 gamma = prevKey + (rectTop-prevValue)*keyPerValue;
18234 if (gamma >= rectLeft && gamma <= rectRight)
17735 if (gamma >= rectLeft && gamma <= rectRight)
18235 intersections.append(QPointF(gamma, rectTop));
17736 intersections.append(QPointF(gamma, rectTop));
18236 // check bottom of rect:
17737 // check bottom of rect:
18237 gamma = prevKey + (rectBottom-prevValue)*keyPerValue;
17738 gamma = prevKey + (rectBottom-prevValue)*keyPerValue;
18238 if (gamma >= rectLeft && gamma <= rectRight)
17739 if (gamma >= rectLeft && gamma <= rectRight)
18239 intersections.append(QPointF(gamma, rectBottom));
17740 intersections.append(QPointF(gamma, rectBottom));
18240 double valuePerKey = 1.0/keyPerValue;
17741 double valuePerKey = 1.0/keyPerValue;
18241 // check left of rect:
17742 // check left of rect:
18242 gamma = prevValue + (rectLeft-prevKey)*valuePerKey;
17743 gamma = prevValue + (rectLeft-prevKey)*valuePerKey;
18243 if (gamma >= rectBottom && gamma <= rectTop)
17744 if (gamma >= rectBottom && gamma <= rectTop)
18244 intersections.append(QPointF(rectLeft, gamma));
17745 intersections.append(QPointF(rectLeft, gamma));
18245 // check right of rect:
17746 // check right of rect:
18246 gamma = prevValue + (rectRight-prevKey)*valuePerKey;
17747 gamma = prevValue + (rectRight-prevKey)*valuePerKey;
18247 if (gamma >= rectBottom && gamma <= rectTop)
17748 if (gamma >= rectBottom && gamma <= rectTop)
18248 intersections.append(QPointF(rectRight, gamma));
17749 intersections.append(QPointF(rectRight, gamma));
18249 }
17750 }
18250
17751
18251 // handle cases where found points isn't exactly 2:
17752 // handle cases where found points isn't exactly 2:
18252 if (intersections.size() > 2)
17753 if (intersections.size() > 2)
18253 {
17754 {
18254 // line probably goes through corner of rect, and we got duplicate points there. single out the point pair with greatest distance in between:
17755 // line probably goes through corner of rect, and we got duplicate points there. single out the point pair with greatest distance in between:
18255 double distSqrMax = 0;
17756 double distSqrMax = 0;
18256 QPointF pv1, pv2;
17757 QPointF pv1, pv2;
18257 for (int i=0; i<intersections.size()-1; ++i)
17758 for (int i=0; i<intersections.size()-1; ++i)
18258 {
17759 {
18259 for (int k=i+1; k<intersections.size(); ++k)
17760 for (int k=i+1; k<intersections.size(); ++k)
18260 {
17761 {
18261 QPointF distPoint = intersections.at(i)-intersections.at(k);
17762 QPointF distPoint = intersections.at(i)-intersections.at(k);
18262 double distSqr = distPoint.x()*distPoint.x()+distPoint.y()+distPoint.y();
17763 double distSqr = distPoint.x()*distPoint.x()+distPoint.y()+distPoint.y();
18263 if (distSqr > distSqrMax)
17764 if (distSqr > distSqrMax)
18264 {
17765 {
18265 pv1 = intersections.at(i);
17766 pv1 = intersections.at(i);
18266 pv2 = intersections.at(k);
17767 pv2 = intersections.at(k);
18267 distSqrMax = distSqr;
17768 distSqrMax = distSqr;
18268 }
17769 }
18269 }
17770 }
18270 }
17771 }
18271 intersections = QList<QPointF>() << pv1 << pv2;
17772 intersections = QList<QPointF>() << pv1 << pv2;
18272 } else if (intersections.size() != 2)
17773 } else if (intersections.size() != 2)
18273 {
17774 {
18274 // one or even zero points found (shouldn't happen unless line perfectly tangent to corner), no need to draw segment
17775 // one or even zero points found (shouldn't happen unless line perfectly tangent to corner), no need to draw segment
18275 return false;
17776 return false;
18276 }
17777 }
18277
17778
18278 // possibly re-sort points so optimized point segment has same direction as original segment:
17779 // possibly re-sort points so optimized point segment has same direction as original segment:
18279 if ((key-prevKey)*(intersections.at(1).x()-intersections.at(0).x()) + (value-prevValue)*(intersections.at(1).y()-intersections.at(0).y()) < 0) // scalar product of both segments < 0 -> opposite direction
17780 if ((key-prevKey)*(intersections.at(1).x()-intersections.at(0).x()) + (value-prevValue)*(intersections.at(1).y()-intersections.at(0).y()) < 0) // scalar product of both segments < 0 -> opposite direction
18280 intersections.move(0, 1);
17781 intersections.move(0, 1);
18281 crossA = coordsToPixels(intersections.at(0).x(), intersections.at(0).y());
17782 crossA = coordsToPixels(intersections.at(0).x(), intersections.at(0).y());
18282 crossB = coordsToPixels(intersections.at(1).x(), intersections.at(1).y());
17783 crossB = coordsToPixels(intersections.at(1).x(), intersections.at(1).y());
18283 return true;
17784 return true;
18284 }
17785 }
18285
17786
18286 /*! \internal
17787 /*! \internal
@@ -18310,85 +17811,85 bool QCPCurve::getTraverse(double prevKe
18310 */
17811 */
18311 void QCPCurve::getTraverseCornerPoints(int prevRegion, int currentRegion, double rectLeft, double rectTop, double rectRight, double rectBottom, QVector<QPointF> &beforeTraverse, QVector<QPointF> &afterTraverse) const
17812 void QCPCurve::getTraverseCornerPoints(int prevRegion, int currentRegion, double rectLeft, double rectTop, double rectRight, double rectBottom, QVector<QPointF> &beforeTraverse, QVector<QPointF> &afterTraverse) const
18312 {
17813 {
18313 switch (prevRegion)
17814 switch (prevRegion)
18314 {
17815 {
18315 case 1:
17816 case 1:
18316 {
17817 {
18317 switch (currentRegion)
17818 switch (currentRegion)
18318 {
17819 {
18319 case 6: { beforeTraverse << coordsToPixels(rectLeft, rectTop); break; }
17820 case 6: { beforeTraverse << coordsToPixels(rectLeft, rectTop); break; }
18320 case 9: { beforeTraverse << coordsToPixels(rectLeft, rectTop); afterTraverse << coordsToPixels(rectRight, rectBottom); break; }
17821 case 9: { beforeTraverse << coordsToPixels(rectLeft, rectTop); afterTraverse << coordsToPixels(rectRight, rectBottom); break; }
18321 case 8: { beforeTraverse << coordsToPixels(rectLeft, rectTop); break; }
17822 case 8: { beforeTraverse << coordsToPixels(rectLeft, rectTop); break; }
18322 }
17823 }
18323 break;
17824 break;
18324 }
17825 }
18325 case 2:
17826 case 2:
18326 {
17827 {
18327 switch (currentRegion)
17828 switch (currentRegion)
18328 {
17829 {
18329 case 7: { afterTraverse << coordsToPixels(rectRight, rectTop); break; }
17830 case 7: { afterTraverse << coordsToPixels(rectRight, rectTop); break; }
18330 case 9: { afterTraverse << coordsToPixels(rectRight, rectBottom); break; }
17831 case 9: { afterTraverse << coordsToPixels(rectRight, rectBottom); break; }
18331 }
17832 }
18332 break;
17833 break;
18333 }
17834 }
18334 case 3:
17835 case 3:
18335 {
17836 {
18336 switch (currentRegion)
17837 switch (currentRegion)
18337 {
17838 {
18338 case 4: { beforeTraverse << coordsToPixels(rectLeft, rectBottom); break; }
17839 case 4: { beforeTraverse << coordsToPixels(rectLeft, rectBottom); break; }
18339 case 7: { beforeTraverse << coordsToPixels(rectLeft, rectBottom); afterTraverse << coordsToPixels(rectRight, rectTop); break; }
17840 case 7: { beforeTraverse << coordsToPixels(rectLeft, rectBottom); afterTraverse << coordsToPixels(rectRight, rectTop); break; }
18340 case 8: { beforeTraverse << coordsToPixels(rectLeft, rectBottom); break; }
17841 case 8: { beforeTraverse << coordsToPixels(rectLeft, rectBottom); break; }
18341 }
17842 }
18342 break;
17843 break;
18343 }
17844 }
18344 case 4:
17845 case 4:
18345 {
17846 {
18346 switch (currentRegion)
17847 switch (currentRegion)
18347 {
17848 {
18348 case 3: { afterTraverse << coordsToPixels(rectLeft, rectBottom); break; }
17849 case 3: { afterTraverse << coordsToPixels(rectLeft, rectBottom); break; }
18349 case 9: { afterTraverse << coordsToPixels(rectRight, rectBottom); break; }
17850 case 9: { afterTraverse << coordsToPixels(rectRight, rectBottom); break; }
18350 }
17851 }
18351 break;
17852 break;
18352 }
17853 }
18353 case 5: { break; } // shouldn't happen because this method only handles full traverses
17854 case 5: { break; } // shouldn't happen because this method only handles full traverses
18354 case 6:
17855 case 6:
18355 {
17856 {
18356 switch (currentRegion)
17857 switch (currentRegion)
18357 {
17858 {
18358 case 1: { afterTraverse << coordsToPixels(rectLeft, rectTop); break; }
17859 case 1: { afterTraverse << coordsToPixels(rectLeft, rectTop); break; }
18359 case 7: { afterTraverse << coordsToPixels(rectRight, rectTop); break; }
17860 case 7: { afterTraverse << coordsToPixels(rectRight, rectTop); break; }
18360 }
17861 }
18361 break;
17862 break;
18362 }
17863 }
18363 case 7:
17864 case 7:
18364 {
17865 {
18365 switch (currentRegion)
17866 switch (currentRegion)
18366 {
17867 {
18367 case 2: { beforeTraverse << coordsToPixels(rectRight, rectTop); break; }
17868 case 2: { beforeTraverse << coordsToPixels(rectRight, rectTop); break; }
18368 case 3: { beforeTraverse << coordsToPixels(rectRight, rectTop); afterTraverse << coordsToPixels(rectLeft, rectBottom); break; }
17869 case 3: { beforeTraverse << coordsToPixels(rectRight, rectTop); afterTraverse << coordsToPixels(rectLeft, rectBottom); break; }
18369 case 6: { beforeTraverse << coordsToPixels(rectRight, rectTop); break; }
17870 case 6: { beforeTraverse << coordsToPixels(rectRight, rectTop); break; }
18370 }
17871 }
18371 break;
17872 break;
18372 }
17873 }
18373 case 8:
17874 case 8:
18374 {
17875 {
18375 switch (currentRegion)
17876 switch (currentRegion)
18376 {
17877 {
18377 case 1: { afterTraverse << coordsToPixels(rectLeft, rectTop); break; }
17878 case 1: { afterTraverse << coordsToPixels(rectLeft, rectTop); break; }
18378 case 3: { afterTraverse << coordsToPixels(rectLeft, rectBottom); break; }
17879 case 3: { afterTraverse << coordsToPixels(rectLeft, rectBottom); break; }
18379 }
17880 }
18380 break;
17881 break;
18381 }
17882 }
18382 case 9:
17883 case 9:
18383 {
17884 {
18384 switch (currentRegion)
17885 switch (currentRegion)
18385 {
17886 {
18386 case 2: { beforeTraverse << coordsToPixels(rectRight, rectBottom); break; }
17887 case 2: { beforeTraverse << coordsToPixels(rectRight, rectBottom); break; }
18387 case 1: { beforeTraverse << coordsToPixels(rectRight, rectBottom); afterTraverse << coordsToPixels(rectLeft, rectTop); break; }
17888 case 1: { beforeTraverse << coordsToPixels(rectRight, rectBottom); afterTraverse << coordsToPixels(rectLeft, rectTop); break; }
18388 case 4: { beforeTraverse << coordsToPixels(rectRight, rectBottom); break; }
17889 case 4: { beforeTraverse << coordsToPixels(rectRight, rectBottom); break; }
18389 }
17890 }
18390 break;
17891 break;
18391 }
17892 }
18392 }
17893 }
18393 }
17894 }
18394
17895
@@ -18400,95 +17901,95 void QCPCurve::getTraverseCornerPoints(i
18400 */
17901 */
18401 double QCPCurve::pointDistance(const QPointF &pixelPoint) const
17902 double QCPCurve::pointDistance(const QPointF &pixelPoint) const
18402 {
17903 {
18403 if (mData->isEmpty())
17904 if (mData->isEmpty())
18404 {
17905 {
18405 qDebug() << Q_FUNC_INFO << "requested point distance on curve" << mName << "without data";
17906 qDebug() << Q_FUNC_INFO << "requested point distance on curve" << mName << "without data";
18406 return 500;
17907 return 500;
18407 }
17908 }
18408 if (mData->size() == 1)
17909 if (mData->size() == 1)
18409 {
17910 {
18410 QPointF dataPoint = coordsToPixels(mData->constBegin().key(), mData->constBegin().value().value);
17911 QPointF dataPoint = coordsToPixels(mData->constBegin().key(), mData->constBegin().value().value);
18411 return QVector2D(dataPoint-pixelPoint).length();
17912 return QVector2D(dataPoint-pixelPoint).length();
18412 }
17913 }
18413
17914
18414 // calculate minimum distance to line segments:
17915 // calculate minimum distance to line segments:
18415 QVector<QPointF> *lineData = new QVector<QPointF>;
17916 QVector<QPointF> *lineData = new QVector<QPointF>;
18416 getCurveData(lineData);
17917 getCurveData(lineData);
18417 double minDistSqr = std::numeric_limits<double>::max();
17918 double minDistSqr = std::numeric_limits<double>::max();
18418 for (int i=0; i<lineData->size()-1; ++i)
17919 for (int i=0; i<lineData->size()-1; ++i)
18419 {
17920 {
18420 double currentDistSqr = distSqrToLine(lineData->at(i), lineData->at(i+1), pixelPoint);
17921 double currentDistSqr = distSqrToLine(lineData->at(i), lineData->at(i+1), pixelPoint);
18421 if (currentDistSqr < minDistSqr)
17922 if (currentDistSqr < minDistSqr)
18422 minDistSqr = currentDistSqr;
17923 minDistSqr = currentDistSqr;
18423 }
17924 }
18424 delete lineData;
17925 delete lineData;
18425 return qSqrt(minDistSqr);
17926 return qSqrt(minDistSqr);
18426 }
17927 }
18427
17928
18428 /* inherits documentation from base class */
17929 /* inherits documentation from base class */
18429 QCPRange QCPCurve::getKeyRange(bool &foundRange, SignDomain inSignDomain) const
17930 QCPRange QCPCurve::getKeyRange(bool &foundRange, SignDomain inSignDomain) const
18430 {
17931 {
18431 QCPRange range;
17932 QCPRange range;
18432 bool haveLower = false;
17933 bool haveLower = false;
18433 bool haveUpper = false;
17934 bool haveUpper = false;
18434
17935
18435 double current;
17936 double current;
18436
17937
18437 QCPCurveDataMap::const_iterator it = mData->constBegin();
17938 QCPCurveDataMap::const_iterator it = mData->constBegin();
18438 while (it != mData->constEnd())
17939 while (it != mData->constEnd())
18439 {
17940 {
18440 current = it.value().key;
17941 current = it.value().key;
18441 if (inSignDomain == sdBoth || (inSignDomain == sdNegative && current < 0) || (inSignDomain == sdPositive && current > 0))
17942 if (inSignDomain == sdBoth || (inSignDomain == sdNegative && current < 0) || (inSignDomain == sdPositive && current > 0))
18442 {
17943 {
18443 if (current < range.lower || !haveLower)
17944 if (current < range.lower || !haveLower)
18444 {
17945 {
18445 range.lower = current;
17946 range.lower = current;
18446 haveLower = true;
17947 haveLower = true;
18447 }
17948 }
18448 if (current > range.upper || !haveUpper)
17949 if (current > range.upper || !haveUpper)
18449 {
17950 {
18450 range.upper = current;
17951 range.upper = current;
18451 haveUpper = true;
17952 haveUpper = true;
18452 }
17953 }
18453 }
17954 }
18454 ++it;
17955 ++it;
18455 }
17956 }
18456
17957
18457 foundRange = haveLower && haveUpper;
17958 foundRange = haveLower && haveUpper;
18458 return range;
17959 return range;
18459 }
17960 }
18460
17961
18461 /* inherits documentation from base class */
17962 /* inherits documentation from base class */
18462 QCPRange QCPCurve::getValueRange(bool &foundRange, SignDomain inSignDomain) const
17963 QCPRange QCPCurve::getValueRange(bool &foundRange, SignDomain inSignDomain) const
18463 {
17964 {
18464 QCPRange range;
17965 QCPRange range;
18465 bool haveLower = false;
17966 bool haveLower = false;
18466 bool haveUpper = false;
17967 bool haveUpper = false;
18467
17968
18468 double current;
17969 double current;
18469
17970
18470 QCPCurveDataMap::const_iterator it = mData->constBegin();
17971 QCPCurveDataMap::const_iterator it = mData->constBegin();
18471 while (it != mData->constEnd())
17972 while (it != mData->constEnd())
18472 {
17973 {
18473 current = it.value().value;
17974 current = it.value().value;
18474 if (inSignDomain == sdBoth || (inSignDomain == sdNegative && current < 0) || (inSignDomain == sdPositive && current > 0))
17975 if (inSignDomain == sdBoth || (inSignDomain == sdNegative && current < 0) || (inSignDomain == sdPositive && current > 0))
18475 {
17976 {
18476 if (current < range.lower || !haveLower)
17977 if (current < range.lower || !haveLower)
18477 {
17978 {
18478 range.lower = current;
17979 range.lower = current;
18479 haveLower = true;
17980 haveLower = true;
18480 }
17981 }
18481 if (current > range.upper || !haveUpper)
17982 if (current > range.upper || !haveUpper)
18482 {
17983 {
18483 range.upper = current;
17984 range.upper = current;
18484 haveUpper = true;
17985 haveUpper = true;
18485 }
17986 }
18486 }
17987 }
18487 ++it;
17988 ++it;
18488 }
17989 }
18489
17990
18490 foundRange = haveLower && haveUpper;
17991 foundRange = haveLower && haveUpper;
18491 return range;
17992 return range;
18492 }
17993 }
18493
17994
18494
17995
@@ -18563,16 +18064,16 QCPRange QCPCurve::getValueRange(bool &f
18563 Constructs a new bars group for the specified QCustomPlot instance.
18064 Constructs a new bars group for the specified QCustomPlot instance.
18564 */
18065 */
18565 QCPBarsGroup::QCPBarsGroup(QCustomPlot *parentPlot) :
18066 QCPBarsGroup::QCPBarsGroup(QCustomPlot *parentPlot) :
18566 QObject(parentPlot),
18067 QObject(parentPlot),
18567 mParentPlot(parentPlot),
18068 mParentPlot(parentPlot),
18568 mSpacingType(stAbsolute),
18069 mSpacingType(stAbsolute),
18569 mSpacing(4)
18070 mSpacing(4)
18570 {
18071 {
18571 }
18072 }
18572
18073
18573 QCPBarsGroup::~QCPBarsGroup()
18074 QCPBarsGroup::~QCPBarsGroup()
18574 {
18075 {
18575 clear();
18076 clear();
18576 }
18077 }
18577
18078
18578 /*!
18079 /*!
@@ -18584,7 +18085,7 QCPBarsGroup::~QCPBarsGroup()
18584 */
18085 */
18585 void QCPBarsGroup::setSpacingType(SpacingType spacingType)
18086 void QCPBarsGroup::setSpacingType(SpacingType spacingType)
18586 {
18087 {
18587 mSpacingType = spacingType;
18088 mSpacingType = spacingType;
18588 }
18089 }
18589
18090
18590 /*!
18091 /*!
@@ -18595,7 +18096,7 void QCPBarsGroup::setSpacingType(Spacin
18595 */
18096 */
18596 void QCPBarsGroup::setSpacing(double spacing)
18097 void QCPBarsGroup::setSpacing(double spacing)
18597 {
18098 {
18598 mSpacing = spacing;
18099 mSpacing = spacing;
18599 }
18100 }
18600
18101
18601 /*!
18102 /*!
@@ -18606,13 +18107,13 void QCPBarsGroup::setSpacing(double spa
18606 */
18107 */
18607 QCPBars *QCPBarsGroup::bars(int index) const
18108 QCPBars *QCPBarsGroup::bars(int index) const
18608 {
18109 {
18609 if (index >= 0 && index < mBars.size())
18110 if (index >= 0 && index < mBars.size())
18610 {
18111 {
18611 return mBars.at(index);
18112 return mBars.at(index);
18612 } else
18113 } else
18613 {
18114 {
18614 qDebug() << Q_FUNC_INFO << "index out of bounds:" << index;
18115 qDebug() << Q_FUNC_INFO << "index out of bounds:" << index;
18615 return 0;
18116 return 0;
18616 }
18117 }
18617 }
18118 }
18618
18119
@@ -18623,8 +18124,8 QCPBars *QCPBarsGroup::bars(int index) c
18623 */
18124 */
18624 void QCPBarsGroup::clear()
18125 void QCPBarsGroup::clear()
18625 {
18126 {
18626 foreach (QCPBars *bars, mBars) // since foreach takes a copy, removing bars in the loop is okay
18127 foreach (QCPBars *bars, mBars) // since foreach takes a copy, removing bars in the loop is okay
18627 bars->setBarsGroup(0); // removes itself via removeBars
18128 bars->setBarsGroup(0); // removes itself via removeBars
18628 }
18129 }
18629
18130
18630 /*!
18131 /*!
@@ -18635,16 +18136,16 void QCPBarsGroup::clear()
18635 */
18136 */
18636 void QCPBarsGroup::append(QCPBars *bars)
18137 void QCPBarsGroup::append(QCPBars *bars)
18637 {
18138 {
18638 if (!bars)
18139 if (!bars)
18639 {
18140 {
18640 qDebug() << Q_FUNC_INFO << "bars is 0";
18141 qDebug() << Q_FUNC_INFO << "bars is 0";
18641 return;
18142 return;
18642 }
18143 }
18643
18144
18644 if (!mBars.contains(bars))
18145 if (!mBars.contains(bars))
18645 bars->setBarsGroup(this);
18146 bars->setBarsGroup(this);
18646 else
18147 else
18647 qDebug() << Q_FUNC_INFO << "bars plottable is already in this bars group:" << reinterpret_cast<quintptr>(bars);
18148 qDebug() << Q_FUNC_INFO << "bars plottable is already in this bars group:" << reinterpret_cast<quintptr>(bars);
18648 }
18149 }
18649
18150
18650 /*!
18151 /*!
@@ -18658,17 +18159,17 void QCPBarsGroup::append(QCPBars *bars)
18658 */
18159 */
18659 void QCPBarsGroup::insert(int i, QCPBars *bars)
18160 void QCPBarsGroup::insert(int i, QCPBars *bars)
18660 {
18161 {
18661 if (!bars)
18162 if (!bars)
18662 {
18163 {
18663 qDebug() << Q_FUNC_INFO << "bars is 0";
18164 qDebug() << Q_FUNC_INFO << "bars is 0";
18664 return;
18165 return;
18665 }
18166 }
18666
18167
18667 // first append to bars list normally:
18168 // first append to bars list normally:
18668 if (!mBars.contains(bars))
18169 if (!mBars.contains(bars))
18669 bars->setBarsGroup(this);
18170 bars->setBarsGroup(this);
18670 // then move to according position:
18171 // then move to according position:
18671 mBars.move(mBars.indexOf(bars), qBound(0, i, mBars.size()-1));
18172 mBars.move(mBars.indexOf(bars), qBound(0, i, mBars.size()-1));
18672 }
18173 }
18673
18174
18674 /*!
18175 /*!
@@ -18678,16 +18179,16 void QCPBarsGroup::insert(int i, QCPBars
18678 */
18179 */
18679 void QCPBarsGroup::remove(QCPBars *bars)
18180 void QCPBarsGroup::remove(QCPBars *bars)
18680 {
18181 {
18681 if (!bars)
18182 if (!bars)
18682 {
18183 {
18683 qDebug() << Q_FUNC_INFO << "bars is 0";
18184 qDebug() << Q_FUNC_INFO << "bars is 0";
18684 return;
18185 return;
18685 }
18186 }
18686
18187
18687 if (mBars.contains(bars))
18188 if (mBars.contains(bars))
18688 bars->setBarsGroup(0);
18189 bars->setBarsGroup(0);
18689 else
18190 else
18690 qDebug() << Q_FUNC_INFO << "bars plottable is not in this bars group:" << reinterpret_cast<quintptr>(bars);
18191 qDebug() << Q_FUNC_INFO << "bars plottable is not in this bars group:" << reinterpret_cast<quintptr>(bars);
18691 }
18192 }
18692
18193
18693 /*! \internal
18194 /*! \internal
@@ -18699,8 +18200,8 void QCPBarsGroup::remove(QCPBars *bars)
18699 */
18200 */
18700 void QCPBarsGroup::registerBars(QCPBars *bars)
18201 void QCPBarsGroup::registerBars(QCPBars *bars)
18701 {
18202 {
18702 if (!mBars.contains(bars))
18203 if (!mBars.contains(bars))
18703 mBars.append(bars);
18204 mBars.append(bars);
18704 }
18205 }
18705
18206
18706 /*! \internal
18207 /*! \internal
@@ -18712,7 +18213,7 void QCPBarsGroup::registerBars(QCPBars
18712 */
18213 */
18713 void QCPBarsGroup::unregisterBars(QCPBars *bars)
18214 void QCPBarsGroup::unregisterBars(QCPBars *bars)
18714 {
18215 {
18715 mBars.removeOne(bars);
18216 mBars.removeOne(bars);
18716 }
18217 }
18717
18218
18718 /*! \internal
18219 /*! \internal
@@ -18723,77 +18224,77 void QCPBarsGroup::unregisterBars(QCPBar
18723 */
18224 */
18724 double QCPBarsGroup::keyPixelOffset(const QCPBars *bars, double keyCoord)
18225 double QCPBarsGroup::keyPixelOffset(const QCPBars *bars, double keyCoord)
18725 {
18226 {
18726 // find list of all base bars in case some mBars are stacked:
18227 // find list of all base bars in case some mBars are stacked:
18727 QList<const QCPBars*> baseBars;
18228 QList<const QCPBars*> baseBars;
18728 foreach (const QCPBars *b, mBars)
18229 foreach (const QCPBars *b, mBars)
18729 {
18230 {
18730 while (b->barBelow())
18231 while (b->barBelow())
18731 b = b->barBelow();
18232 b = b->barBelow();
18732 if (!baseBars.contains(b))
18233 if (!baseBars.contains(b))
18733 baseBars.append(b);
18234 baseBars.append(b);
18734 }
18235 }
18735 // find base bar this "bars" is stacked on:
18236 // find base bar this "bars" is stacked on:
18736 const QCPBars *thisBase = bars;
18237 const QCPBars *thisBase = bars;
18737 while (thisBase->barBelow())
18238 while (thisBase->barBelow())
18738 thisBase = thisBase->barBelow();
18239 thisBase = thisBase->barBelow();
18739
18240
18740 // determine key pixel offset of this base bars considering all other base bars in this barsgroup:
18241 // determine key pixel offset of this base bars considering all other base bars in this barsgroup:
18741 double result = 0;
18242 double result = 0;
18742 int index = baseBars.indexOf(thisBase);
18243 int index = baseBars.indexOf(thisBase);
18743 if (index >= 0)
18244 if (index >= 0)
18744 {
18245 {
18745 int startIndex;
18246 int startIndex;
18746 double lowerPixelWidth, upperPixelWidth;
18247 double lowerPixelWidth, upperPixelWidth;
18747 if (baseBars.size() % 2 == 1 && index == (baseBars.size()-1)/2) // is center bar (int division on purpose)
18248 if (baseBars.size() % 2 == 1 && index == (baseBars.size()-1)/2) // is center bar (int division on purpose)
18748 {
18249 {
18749 return result;
18250 return result;
18750 } else if (index < (baseBars.size()-1)/2.0) // bar is to the left of center
18251 } else if (index < (baseBars.size()-1)/2.0) // bar is to the left of center
18751 {
18252 {
18752 if (baseBars.size() % 2 == 0) // even number of bars
18253 if (baseBars.size() % 2 == 0) // even number of bars
18753 {
18254 {
18754 startIndex = baseBars.size()/2-1;
18255 startIndex = baseBars.size()/2-1;
18755 result -= getPixelSpacing(baseBars.at(startIndex), keyCoord)*0.5; // half of middle spacing
18256 result -= getPixelSpacing(baseBars.at(startIndex), keyCoord)*0.5; // half of middle spacing
18756 } else // uneven number of bars
18257 } else // uneven number of bars
18757 {
18258 {
18758 startIndex = (baseBars.size()-1)/2-1;
18259 startIndex = (baseBars.size()-1)/2-1;
18759 baseBars.at((baseBars.size()-1)/2)->getPixelWidth(keyCoord, lowerPixelWidth, upperPixelWidth);
18260 baseBars.at((baseBars.size()-1)/2)->getPixelWidth(keyCoord, lowerPixelWidth, upperPixelWidth);
18760 result -= qAbs(upperPixelWidth-lowerPixelWidth)*0.5; // half of center bar
18261 result -= qAbs(upperPixelWidth-lowerPixelWidth)*0.5; // half of center bar
18761 result -= getPixelSpacing(baseBars.at((baseBars.size()-1)/2), keyCoord); // center bar spacing
18262 result -= getPixelSpacing(baseBars.at((baseBars.size()-1)/2), keyCoord); // center bar spacing
18762 }
18263 }
18763 for (int i=startIndex; i>index; --i) // add widths and spacings of bars in between center and our bars
18264 for (int i=startIndex; i>index; --i) // add widths and spacings of bars in between center and our bars
18764 {
18265 {
18765 baseBars.at(i)->getPixelWidth(keyCoord, lowerPixelWidth, upperPixelWidth);
18266 baseBars.at(i)->getPixelWidth(keyCoord, lowerPixelWidth, upperPixelWidth);
18766 result -= qAbs(upperPixelWidth-lowerPixelWidth);
18267 result -= qAbs(upperPixelWidth-lowerPixelWidth);
18767 result -= getPixelSpacing(baseBars.at(i), keyCoord);
18268 result -= getPixelSpacing(baseBars.at(i), keyCoord);
18768 }
18269 }
18769 // finally half of our bars width:
18270 // finally half of our bars width:
18770 baseBars.at(index)->getPixelWidth(keyCoord, lowerPixelWidth, upperPixelWidth);
18271 baseBars.at(index)->getPixelWidth(keyCoord, lowerPixelWidth, upperPixelWidth);
18771 result -= qAbs(upperPixelWidth-lowerPixelWidth)*0.5;
18272 result -= qAbs(upperPixelWidth-lowerPixelWidth)*0.5;
18772 } else // bar is to the right of center
18273 } else // bar is to the right of center
18773 {
18274 {
18774 if (baseBars.size() % 2 == 0) // even number of bars
18275 if (baseBars.size() % 2 == 0) // even number of bars
18775 {
18276 {
18776 startIndex = baseBars.size()/2;
18277 startIndex = baseBars.size()/2;
18777 result += getPixelSpacing(baseBars.at(startIndex), keyCoord)*0.5; // half of middle spacing
18278 result += getPixelSpacing(baseBars.at(startIndex), keyCoord)*0.5; // half of middle spacing
18778 } else // uneven number of bars
18279 } else // uneven number of bars
18779 {
18280 {
18780 startIndex = (baseBars.size()-1)/2+1;
18281 startIndex = (baseBars.size()-1)/2+1;
18781 baseBars.at((baseBars.size()-1)/2)->getPixelWidth(keyCoord, lowerPixelWidth, upperPixelWidth);
18282 baseBars.at((baseBars.size()-1)/2)->getPixelWidth(keyCoord, lowerPixelWidth, upperPixelWidth);
18782 result += qAbs(upperPixelWidth-lowerPixelWidth)*0.5; // half of center bar
18283 result += qAbs(upperPixelWidth-lowerPixelWidth)*0.5; // half of center bar
18783 result += getPixelSpacing(baseBars.at((baseBars.size()-1)/2), keyCoord); // center bar spacing
18284 result += getPixelSpacing(baseBars.at((baseBars.size()-1)/2), keyCoord); // center bar spacing
18784 }
18285 }
18785 for (int i=startIndex; i<index; ++i) // add widths and spacings of bars in between center and our bars
18286 for (int i=startIndex; i<index; ++i) // add widths and spacings of bars in between center and our bars
18786 {
18287 {
18787 baseBars.at(i)->getPixelWidth(keyCoord, lowerPixelWidth, upperPixelWidth);
18288 baseBars.at(i)->getPixelWidth(keyCoord, lowerPixelWidth, upperPixelWidth);
18788 result += qAbs(upperPixelWidth-lowerPixelWidth);
18289 result += qAbs(upperPixelWidth-lowerPixelWidth);
18789 result += getPixelSpacing(baseBars.at(i), keyCoord);
18290 result += getPixelSpacing(baseBars.at(i), keyCoord);
18790 }
18291 }
18791 // finally half of our bars width:
18292 // finally half of our bars width:
18792 baseBars.at(index)->getPixelWidth(keyCoord, lowerPixelWidth, upperPixelWidth);
18293 baseBars.at(index)->getPixelWidth(keyCoord, lowerPixelWidth, upperPixelWidth);
18793 result += qAbs(upperPixelWidth-lowerPixelWidth)*0.5;
18294 result += qAbs(upperPixelWidth-lowerPixelWidth)*0.5;
18794 }
18295 }
18795 }
18296 }
18796 return result;
18297 return result;
18797 }
18298 }
18798
18299
18799 /*! \internal
18300 /*! \internal
@@ -18808,26 +18309,26 double QCPBarsGroup::keyPixelOffset(cons
18808 */
18309 */
18809 double QCPBarsGroup::getPixelSpacing(const QCPBars *bars, double keyCoord)
18310 double QCPBarsGroup::getPixelSpacing(const QCPBars *bars, double keyCoord)
18810 {
18311 {
18811 switch (mSpacingType)
18312 switch (mSpacingType)
18812 {
18313 {
18813 case stAbsolute:
18314 case stAbsolute:
18814 {
18315 {
18815 return mSpacing;
18316 return mSpacing;
18816 }
18317 }
18817 case stAxisRectRatio:
18318 case stAxisRectRatio:
18818 {
18319 {
18819 if (bars->keyAxis()->orientation() == Qt::Horizontal)
18320 if (bars->keyAxis()->orientation() == Qt::Horizontal)
18820 return bars->keyAxis()->axisRect()->width()*mSpacing;
18321 return bars->keyAxis()->axisRect()->width()*mSpacing;
18821 else
18322 else
18822 return bars->keyAxis()->axisRect()->height()*mSpacing;
18323 return bars->keyAxis()->axisRect()->height()*mSpacing;
18823 }
18324 }
18824 case stPlotCoords:
18325 case stPlotCoords:
18825 {
18326 {
18826 double keyPixel = bars->keyAxis()->coordToPixel(keyCoord);
18327 double keyPixel = bars->keyAxis()->coordToPixel(keyCoord);
18827 return bars->keyAxis()->coordToPixel(keyCoord+mSpacing)-keyPixel;
18328 return bars->keyAxis()->coordToPixel(keyCoord+mSpacing)-keyPixel;
18828 }
18329 }
18829 }
18330 }
18830 return 0;
18331 return 0;
18831 }
18332 }
18832
18333
18833
18334
@@ -18851,8 +18352,8 double QCPBarsGroup::getPixelSpacing(con
18851 Constructs a bar data point with key and value set to zero.
18352 Constructs a bar data point with key and value set to zero.
18852 */
18353 */
18853 QCPBarData::QCPBarData() :
18354 QCPBarData::QCPBarData() :
18854 key(0),
18355 key(0),
18855 value(0)
18356 value(0)
18856 {
18357 {
18857 }
18358 }
18858
18359
@@ -18860,8 +18361,8 QCPBarData::QCPBarData() :
18860 Constructs a bar data point with the specified \a key and \a value.
18361 Constructs a bar data point with the specified \a key and \a value.
18861 */
18362 */
18862 QCPBarData::QCPBarData(double key, double value) :
18363 QCPBarData::QCPBarData(double key, double value) :
18863 key(key),
18364 key(key),
18864 value(value)
18365 value(value)
18865 {
18366 {
18866 }
18367 }
18867
18368
@@ -18937,30 +18438,30 QCPBarData::QCPBarData(double key, doubl
18937 then takes ownership of the bar chart.
18438 then takes ownership of the bar chart.
18938 */
18439 */
18939 QCPBars::QCPBars(QCPAxis *keyAxis, QCPAxis *valueAxis) :
18440 QCPBars::QCPBars(QCPAxis *keyAxis, QCPAxis *valueAxis) :
18940 QCPAbstractPlottable(keyAxis, valueAxis),
18441 QCPAbstractPlottable(keyAxis, valueAxis),
18941 mData(new QCPBarDataMap),
18442 mData(new QCPBarDataMap),
18942 mWidth(0.75),
18443 mWidth(0.75),
18943 mWidthType(wtPlotCoords),
18444 mWidthType(wtPlotCoords),
18944 mBarsGroup(0),
18445 mBarsGroup(0),
18945 mBaseValue(0)
18446 mBaseValue(0)
18946 {
18447 {
18947 // modify inherited properties from abstract plottable:
18448 // modify inherited properties from abstract plottable:
18948 mPen.setColor(Qt::blue);
18449 mPen.setColor(Qt::blue);
18949 mPen.setStyle(Qt::SolidLine);
18450 mPen.setStyle(Qt::SolidLine);
18950 mBrush.setColor(QColor(40, 50, 255, 30));
18451 mBrush.setColor(QColor(40, 50, 255, 30));
18951 mBrush.setStyle(Qt::SolidPattern);
18452 mBrush.setStyle(Qt::SolidPattern);
18952 mSelectedPen = mPen;
18453 mSelectedPen = mPen;
18953 mSelectedPen.setWidthF(2.5);
18454 mSelectedPen.setWidthF(2.5);
18954 mSelectedPen.setColor(QColor(80, 80, 255)); // lighter than Qt::blue of mPen
18455 mSelectedPen.setColor(QColor(80, 80, 255)); // lighter than Qt::blue of mPen
18955 mSelectedBrush = mBrush;
18456 mSelectedBrush = mBrush;
18956 }
18457 }
18957
18458
18958 QCPBars::~QCPBars()
18459 QCPBars::~QCPBars()
18959 {
18460 {
18960 setBarsGroup(0);
18461 setBarsGroup(0);
18961 if (mBarBelow || mBarAbove)
18462 if (mBarBelow || mBarAbove)
18962 connectBars(mBarBelow.data(), mBarAbove.data()); // take this bar out of any stacking
18463 connectBars(mBarBelow.data(), mBarAbove.data()); // take this bar out of any stacking
18963 delete mData;
18464 delete mData;
18964 }
18465 }
18965
18466
18966 /*!
18467 /*!
@@ -18971,7 +18472,7 QCPBars::~QCPBars()
18971 */
18472 */
18972 void QCPBars::setWidth(double width)
18473 void QCPBars::setWidth(double width)
18973 {
18474 {
18974 mWidth = width;
18475 mWidth = width;
18975 }
18476 }
18976
18477
18977 /*!
18478 /*!
@@ -18984,7 +18485,7 void QCPBars::setWidth(double width)
18984 */
18485 */
18985 void QCPBars::setWidthType(QCPBars::WidthType widthType)
18486 void QCPBars::setWidthType(QCPBars::WidthType widthType)
18986 {
18487 {
18987 mWidthType = widthType;
18488 mWidthType = widthType;
18988 }
18489 }
18989
18490
18990 /*!
18491 /*!
@@ -18995,13 +18496,13 void QCPBars::setWidthType(QCPBars::Widt
18995 */
18496 */
18996 void QCPBars::setBarsGroup(QCPBarsGroup *barsGroup)
18497 void QCPBars::setBarsGroup(QCPBarsGroup *barsGroup)
18997 {
18498 {
18998 // deregister at old group:
18499 // deregister at old group:
18999 if (mBarsGroup)
18500 if (mBarsGroup)
19000 mBarsGroup->unregisterBars(this);
18501 mBarsGroup->unregisterBars(this);
19001 mBarsGroup = barsGroup;
18502 mBarsGroup = barsGroup;
19002 // register at new group:
18503 // register at new group:
19003 if (mBarsGroup)
18504 if (mBarsGroup)
19004 mBarsGroup->registerBars(this);
18505 mBarsGroup->registerBars(this);
19005 }
18506 }
19006
18507
19007 /*!
18508 /*!
@@ -19018,7 +18519,7 void QCPBars::setBarsGroup(QCPBarsGroup
19018 */
18519 */
19019 void QCPBars::setBaseValue(double baseValue)
18520 void QCPBars::setBaseValue(double baseValue)
19020 {
18521 {
19021 mBaseValue = baseValue;
18522 mBaseValue = baseValue;
19022 }
18523 }
19023
18524
19024 /*!
18525 /*!
@@ -19030,18 +18531,18 void QCPBars::setBaseValue(double baseVa
19030 */
18531 */
19031 void QCPBars::setData(QCPBarDataMap *data, bool copy)
18532 void QCPBars::setData(QCPBarDataMap *data, bool copy)
19032 {
18533 {
19033 if (mData == data)
18534 if (mData == data)
19034 {
18535 {
19035 qDebug() << Q_FUNC_INFO << "The data pointer is already in (and owned by) this plottable" << reinterpret_cast<quintptr>(data);
18536 qDebug() << Q_FUNC_INFO << "The data pointer is already in (and owned by) this plottable" << reinterpret_cast<quintptr>(data);
19036 return;
18537 return;
19037 }
18538 }
19038 if (copy)
18539 if (copy)
19039 {
18540 {
19040 *mData = *data;
18541 *mData = *data;
19041 } else
18542 } else
19042 {
18543 {
19043 delete mData;
18544 delete mData;
19044 mData = data;
18545 mData = data;
19045 }
18546 }
19046 }
18547 }
19047
18548
@@ -19053,15 +18554,15 void QCPBars::setData(QCPBarDataMap *dat
19053 */
18554 */
19054 void QCPBars::setData(const QVector<double> &key, const QVector<double> &value)
18555 void QCPBars::setData(const QVector<double> &key, const QVector<double> &value)
19055 {
18556 {
19056 mData->clear();
18557 mData->clear();
19057 int n = key.size();
18558 int n = key.size();
19058 n = qMin(n, value.size());
18559 n = qMin(n, value.size());
19059 QCPBarData newData;
18560 QCPBarData newData;
19060 for (int i=0; i<n; ++i)
18561 for (int i=0; i<n; ++i)
19061 {
18562 {
19062 newData.key = key[i];
18563 newData.key = key[i];
19063 newData.value = value[i];
18564 newData.value = value[i];
19064 mData->insertMulti(newData.key, newData);
18565 mData->insertMulti(newData.key, newData);
19065 }
18566 }
19066 }
18567 }
19067
18568
@@ -19081,20 +18582,20 void QCPBars::setData(const QVector<doub
19081 */
18582 */
19082 void QCPBars::moveBelow(QCPBars *bars)
18583 void QCPBars::moveBelow(QCPBars *bars)
19083 {
18584 {
19084 if (bars == this) return;
18585 if (bars == this) return;
19085 if (bars && (bars->keyAxis() != mKeyAxis.data() || bars->valueAxis() != mValueAxis.data()))
18586 if (bars && (bars->keyAxis() != mKeyAxis.data() || bars->valueAxis() != mValueAxis.data()))
19086 {
18587 {
19087 qDebug() << Q_FUNC_INFO << "passed QCPBars* doesn't have same key and value axis as this QCPBars";
18588 qDebug() << Q_FUNC_INFO << "passed QCPBars* doesn't have same key and value axis as this QCPBars";
19088 return;
18589 return;
19089 }
18590 }
19090 // remove from stacking:
18591 // remove from stacking:
19091 connectBars(mBarBelow.data(), mBarAbove.data()); // Note: also works if one (or both) of them is 0
18592 connectBars(mBarBelow.data(), mBarAbove.data()); // Note: also works if one (or both) of them is 0
19092 // if new bar given, insert this bar below it:
18593 // if new bar given, insert this bar below it:
19093 if (bars)
18594 if (bars)
19094 {
18595 {
19095 if (bars->mBarBelow)
18596 if (bars->mBarBelow)
19096 connectBars(bars->mBarBelow.data(), this);
18597 connectBars(bars->mBarBelow.data(), this);
19097 connectBars(this, bars);
18598 connectBars(this, bars);
19098 }
18599 }
19099 }
18600 }
19100
18601
@@ -19114,20 +18615,20 void QCPBars::moveBelow(QCPBars *bars)
19114 */
18615 */
19115 void QCPBars::moveAbove(QCPBars *bars)
18616 void QCPBars::moveAbove(QCPBars *bars)
19116 {
18617 {
19117 if (bars == this) return;
18618 if (bars == this) return;
19118 if (bars && (bars->keyAxis() != mKeyAxis.data() || bars->valueAxis() != mValueAxis.data()))
18619 if (bars && (bars->keyAxis() != mKeyAxis.data() || bars->valueAxis() != mValueAxis.data()))
19119 {
18620 {
19120 qDebug() << Q_FUNC_INFO << "passed QCPBars* doesn't have same key and value axis as this QCPBars";
18621 qDebug() << Q_FUNC_INFO << "passed QCPBars* doesn't have same key and value axis as this QCPBars";
19121 return;
18622 return;
19122 }
18623 }
19123 // remove from stacking:
18624 // remove from stacking:
19124 connectBars(mBarBelow.data(), mBarAbove.data()); // Note: also works if one (or both) of them is 0
18625 connectBars(mBarBelow.data(), mBarAbove.data()); // Note: also works if one (or both) of them is 0
19125 // if new bar given, insert this bar above it:
18626 // if new bar given, insert this bar above it:
19126 if (bars)
18627 if (bars)
19127 {
18628 {
19128 if (bars->mBarAbove)
18629 if (bars->mBarAbove)
19129 connectBars(this, bars->mBarAbove.data());
18630 connectBars(this, bars->mBarAbove.data());
19130 connectBars(bars, this);
18631 connectBars(bars, this);
19131 }
18632 }
19132 }
18633 }
19133
18634
@@ -19137,7 +18638,7 void QCPBars::moveAbove(QCPBars *bars)
19137 */
18638 */
19138 void QCPBars::addData(const QCPBarDataMap &dataMap)
18639 void QCPBars::addData(const QCPBarDataMap &dataMap)
19139 {
18640 {
19140 mData->unite(dataMap);
18641 mData->unite(dataMap);
19141 }
18642 }
19142
18643
19143 /*! \overload
18644 /*! \overload
@@ -19146,7 +18647,7 void QCPBars::addData(const QCPBarDataMa
19146 */
18647 */
19147 void QCPBars::addData(const QCPBarData &data)
18648 void QCPBars::addData(const QCPBarData &data)
19148 {
18649 {
19149 mData->insertMulti(data.key, data);
18650 mData->insertMulti(data.key, data);
19150 }
18651 }
19151
18652
19152 /*! \overload
18653 /*! \overload
@@ -19155,10 +18656,10 void QCPBars::addData(const QCPBarData &
19155 */
18656 */
19156 void QCPBars::addData(double key, double value)
18657 void QCPBars::addData(double key, double value)
19157 {
18658 {
19158 QCPBarData newData;
18659 QCPBarData newData;
19159 newData.key = key;
18660 newData.key = key;
19160 newData.value = value;
18661 newData.value = value;
19161 mData->insertMulti(newData.key, newData);
18662 mData->insertMulti(newData.key, newData);
19162 }
18663 }
19163
18664
19164 /*! \overload
18665 /*! \overload
@@ -19167,14 +18668,14 void QCPBars::addData(double key, double
19167 */
18668 */
19168 void QCPBars::addData(const QVector<double> &keys, const QVector<double> &values)
18669 void QCPBars::addData(const QVector<double> &keys, const QVector<double> &values)
19169 {
18670 {
19170 int n = keys.size();
18671 int n = keys.size();
19171 n = qMin(n, values.size());
18672 n = qMin(n, values.size());
19172 QCPBarData newData;
18673 QCPBarData newData;
19173 for (int i=0; i<n; ++i)
18674 for (int i=0; i<n; ++i)
19174 {
18675 {
19175 newData.key = keys[i];
18676 newData.key = keys[i];
19176 newData.value = values[i];
18677 newData.value = values[i];
19177 mData->insertMulti(newData.key, newData);
18678 mData->insertMulti(newData.key, newData);
19178 }
18679 }
19179 }
18680 }
19180
18681
@@ -19184,9 +18685,9 void QCPBars::addData(const QVector<doub
19184 */
18685 */
19185 void QCPBars::removeDataBefore(double key)
18686 void QCPBars::removeDataBefore(double key)
19186 {
18687 {
19187 QCPBarDataMap::iterator it = mData->begin();
18688 QCPBarDataMap::iterator it = mData->begin();
19188 while (it != mData->end() && it.key() < key)
18689 while (it != mData->end() && it.key() < key)
19189 it = mData->erase(it);
18690 it = mData->erase(it);
19190 }
18691 }
19191
18692
19192 /*!
18693 /*!
@@ -19195,10 +18696,10 void QCPBars::removeDataBefore(double ke
19195 */
18696 */
19196 void QCPBars::removeDataAfter(double key)
18697 void QCPBars::removeDataAfter(double key)
19197 {
18698 {
19198 if (mData->isEmpty()) return;
18699 if (mData->isEmpty()) return;
19199 QCPBarDataMap::iterator it = mData->upperBound(key);
18700 QCPBarDataMap::iterator it = mData->upperBound(key);
19200 while (it != mData->end())
18701 while (it != mData->end())
19201 it = mData->erase(it);
18702 it = mData->erase(it);
19202 }
18703 }
19203
18704
19204 /*!
18705 /*!
@@ -19210,11 +18711,11 void QCPBars::removeDataAfter(double key
19210 */
18711 */
19211 void QCPBars::removeData(double fromKey, double toKey)
18712 void QCPBars::removeData(double fromKey, double toKey)
19212 {
18713 {
19213 if (fromKey >= toKey || mData->isEmpty()) return;
18714 if (fromKey >= toKey || mData->isEmpty()) return;
19214 QCPBarDataMap::iterator it = mData->upperBound(fromKey);
18715 QCPBarDataMap::iterator it = mData->upperBound(fromKey);
19215 QCPBarDataMap::iterator itEnd = mData->upperBound(toKey);
18716 QCPBarDataMap::iterator itEnd = mData->upperBound(toKey);
19216 while (it != itEnd)
18717 while (it != itEnd)
19217 it = mData->erase(it);
18718 it = mData->erase(it);
19218 }
18719 }
19219
18720
19220 /*! \overload
18721 /*! \overload
@@ -19227,7 +18728,7 void QCPBars::removeData(double fromKey,
19227 */
18728 */
19228 void QCPBars::removeData(double key)
18729 void QCPBars::removeData(double key)
19229 {
18730 {
19230 mData->remove(key);
18731 mData->remove(key);
19231 }
18732 }
19232
18733
19233 /*!
18734 /*!
@@ -19236,60 +18737,60 void QCPBars::removeData(double key)
19236 */
18737 */
19237 void QCPBars::clearData()
18738 void QCPBars::clearData()
19238 {
18739 {
19239 mData->clear();
18740 mData->clear();
19240 }
18741 }
19241
18742
19242 /* inherits documentation from base class */
18743 /* inherits documentation from base class */
19243 double QCPBars::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
18744 double QCPBars::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
19244 {
18745 {
19245 Q_UNUSED(details)
18746 Q_UNUSED(details)
19246 if (onlySelectable && !mSelectable)
18747 if (onlySelectable && !mSelectable)
18748 return -1;
18749 if (!mKeyAxis || !mValueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return -1; }
18750
18751 if (mKeyAxis.data()->axisRect()->rect().contains(pos.toPoint()))
18752 {
18753 QCPBarDataMap::ConstIterator it;
18754 for (it = mData->constBegin(); it != mData->constEnd(); ++it)
18755 {
18756 if (getBarPolygon(it.value().key, it.value().value).boundingRect().contains(pos))
18757 return mParentPlot->selectionTolerance()*0.99;
18758 }
18759 }
19247 return -1;
18760 return -1;
19248 if (!mKeyAxis || !mValueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return -1; }
19249
19250 if (mKeyAxis.data()->axisRect()->rect().contains(pos.toPoint()))
19251 {
19252 QCPBarDataMap::ConstIterator it;
19253 for (it = mData->constBegin(); it != mData->constEnd(); ++it)
19254 {
19255 if (getBarPolygon(it.value().key, it.value().value).boundingRect().contains(pos))
19256 return mParentPlot->selectionTolerance()*0.99;
19257 }
19258 }
19259 return -1;
19260 }
18761 }
19261
18762
19262 /* inherits documentation from base class */
18763 /* inherits documentation from base class */
19263 void QCPBars::draw(QCPPainter *painter)
18764 void QCPBars::draw(QCPPainter *painter)
19264 {
18765 {
19265 if (!mKeyAxis || !mValueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
18766 if (!mKeyAxis || !mValueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
19266 if (mData->isEmpty()) return;
18767 if (mData->isEmpty()) return;
19267
18768
19268 QCPBarDataMap::const_iterator it, lower, upperEnd;
18769 QCPBarDataMap::const_iterator it, lower, upperEnd;
19269 getVisibleDataBounds(lower, upperEnd);
18770 getVisibleDataBounds(lower, upperEnd);
19270 for (it = lower; it != upperEnd; ++it)
18771 for (it = lower; it != upperEnd; ++it)
19271 {
18772 {
19272 // check data validity if flag set:
18773 // check data validity if flag set:
19273 #ifdef QCUSTOMPLOT_CHECK_DATA
18774 #ifdef QCUSTOMPLOT_CHECK_DATA
19274 if (QCP::isInvalidData(it.value().key, it.value().value))
18775 if (QCP::isInvalidData(it.value().key, it.value().value))
19275 qDebug() << Q_FUNC_INFO << "Data point at" << it.key() << "of drawn range invalid." << "Plottable name:" << name();
18776 qDebug() << Q_FUNC_INFO << "Data point at" << it.key() << "of drawn range invalid." << "Plottable name:" << name();
19276 #endif
18777 #endif
19277 QPolygonF barPolygon = getBarPolygon(it.key(), it.value().value);
18778 QPolygonF barPolygon = getBarPolygon(it.key(), it.value().value);
19278 // draw bar fill:
18779 // draw bar fill:
19279 if (mainBrush().style() != Qt::NoBrush && mainBrush().color().alpha() != 0)
18780 if (mainBrush().style() != Qt::NoBrush && mainBrush().color().alpha() != 0)
19280 {
18781 {
19281 applyFillAntialiasingHint(painter);
18782 applyFillAntialiasingHint(painter);
19282 painter->setPen(Qt::NoPen);
18783 painter->setPen(Qt::NoPen);
19283 painter->setBrush(mainBrush());
18784 painter->setBrush(mainBrush());
19284 painter->drawPolygon(barPolygon);
18785 painter->drawPolygon(barPolygon);
19285 }
18786 }
19286 // draw bar line:
18787 // draw bar line:
19287 if (mainPen().style() != Qt::NoPen && mainPen().color().alpha() != 0)
18788 if (mainPen().style() != Qt::NoPen && mainPen().color().alpha() != 0)
19288 {
18789 {
19289 applyDefaultAntialiasingHint(painter);
18790 applyDefaultAntialiasingHint(painter);
19290 painter->setPen(mainPen());
18791 painter->setPen(mainPen());
19291 painter->setBrush(Qt::NoBrush);
18792 painter->setBrush(Qt::NoBrush);
19292 painter->drawPolyline(barPolygon);
18793 painter->drawPolyline(barPolygon);
19293 }
18794 }
19294 }
18795 }
19295 }
18796 }
@@ -19297,13 +18798,13 void QCPBars::draw(QCPPainter *painter)
19297 /* inherits documentation from base class */
18798 /* inherits documentation from base class */
19298 void QCPBars::drawLegendIcon(QCPPainter *painter, const QRectF &rect) const
18799 void QCPBars::drawLegendIcon(QCPPainter *painter, const QRectF &rect) const
19299 {
18800 {
19300 // draw filled rect:
18801 // draw filled rect:
19301 applyDefaultAntialiasingHint(painter);
18802 applyDefaultAntialiasingHint(painter);
19302 painter->setBrush(mBrush);
18803 painter->setBrush(mBrush);
19303 painter->setPen(mPen);
18804 painter->setPen(mPen);
19304 QRectF r = QRectF(0, 0, rect.width()*0.67, rect.height()*0.67);
18805 QRectF r = QRectF(0, 0, rect.width()*0.67, rect.height()*0.67);
19305 r.moveCenter(rect.center());
18806 r.moveCenter(rect.center());
19306 painter->drawRect(r);
18807 painter->drawRect(r);
19307 }
18808 }
19308
18809
19309 /*! \internal
18810 /*! \internal
@@ -19322,49 +18823,49 void QCPBars::drawLegendIcon(QCPPainter
19322 */
18823 */
19323 void QCPBars::getVisibleDataBounds(QCPBarDataMap::const_iterator &lower, QCPBarDataMap::const_iterator &upperEnd) const
18824 void QCPBars::getVisibleDataBounds(QCPBarDataMap::const_iterator &lower, QCPBarDataMap::const_iterator &upperEnd) const
19324 {
18825 {
19325 if (!mKeyAxis) { qDebug() << Q_FUNC_INFO << "invalid key axis"; return; }
18826 if (!mKeyAxis) { qDebug() << Q_FUNC_INFO << "invalid key axis"; return; }
19326 if (mData->isEmpty())
18827 if (mData->isEmpty())
19327 {
18828 {
19328 lower = mData->constEnd();
18829 lower = mData->constEnd();
19329 upperEnd = mData->constEnd();
18830 upperEnd = mData->constEnd();
19330 return;
18831 return;
19331 }
18832 }
19332
18833
19333 // get visible data range as QMap iterators
18834 // get visible data range as QMap iterators
19334 lower = mData->lowerBound(mKeyAxis.data()->range().lower);
18835 lower = mData->lowerBound(mKeyAxis.data()->range().lower);
19335 upperEnd = mData->upperBound(mKeyAxis.data()->range().upper);
18836 upperEnd = mData->upperBound(mKeyAxis.data()->range().upper);
19336 double lowerPixelBound = mKeyAxis.data()->coordToPixel(mKeyAxis.data()->range().lower);
18837 double lowerPixelBound = mKeyAxis.data()->coordToPixel(mKeyAxis.data()->range().lower);
19337 double upperPixelBound = mKeyAxis.data()->coordToPixel(mKeyAxis.data()->range().upper);
18838 double upperPixelBound = mKeyAxis.data()->coordToPixel(mKeyAxis.data()->range().upper);
19338 bool isVisible = false;
18839 bool isVisible = false;
19339 // walk left from lbound to find lower bar that actually is completely outside visible pixel range:
18840 // walk left from lbound to find lower bar that actually is completely outside visible pixel range:
19340 QCPBarDataMap::const_iterator it = lower;
18841 QCPBarDataMap::const_iterator it = lower;
19341 while (it != mData->constBegin())
18842 while (it != mData->constBegin())
19342 {
18843 {
19343 --it;
18844 --it;
19344 QRectF barBounds = getBarPolygon(it.value().key, it.value().value).boundingRect();
18845 QRectF barBounds = getBarPolygon(it.value().key, it.value().value).boundingRect();
19345 if (mKeyAxis.data()->orientation() == Qt::Horizontal)
18846 if (mKeyAxis.data()->orientation() == Qt::Horizontal)
19346 isVisible = ((!mKeyAxis.data()->rangeReversed() && barBounds.right() >= lowerPixelBound) || (mKeyAxis.data()->rangeReversed() && barBounds.left() <= lowerPixelBound));
18847 isVisible = ((!mKeyAxis.data()->rangeReversed() && barBounds.right() >= lowerPixelBound) || (mKeyAxis.data()->rangeReversed() && barBounds.left() <= lowerPixelBound));
19347 else // keyaxis is vertical
18848 else // keyaxis is vertical
19348 isVisible = ((!mKeyAxis.data()->rangeReversed() && barBounds.top() <= lowerPixelBound) || (mKeyAxis.data()->rangeReversed() && barBounds.bottom() >= lowerPixelBound));
18849 isVisible = ((!mKeyAxis.data()->rangeReversed() && barBounds.top() <= lowerPixelBound) || (mKeyAxis.data()->rangeReversed() && barBounds.bottom() >= lowerPixelBound));
19349 if (isVisible)
18850 if (isVisible)
19350 lower = it;
18851 lower = it;
19351 else
18852 else
19352 break;
18853 break;
19353 }
18854 }
19354 // walk right from ubound to find upper bar that actually is completely outside visible pixel range:
18855 // walk right from ubound to find upper bar that actually is completely outside visible pixel range:
19355 it = upperEnd;
18856 it = upperEnd;
19356 while (it != mData->constEnd())
18857 while (it != mData->constEnd())
19357 {
18858 {
19358 QRectF barBounds = getBarPolygon(upperEnd.value().key, upperEnd.value().value).boundingRect();
18859 QRectF barBounds = getBarPolygon(upperEnd.value().key, upperEnd.value().value).boundingRect();
19359 if (mKeyAxis.data()->orientation() == Qt::Horizontal)
18860 if (mKeyAxis.data()->orientation() == Qt::Horizontal)
19360 isVisible = ((!mKeyAxis.data()->rangeReversed() && barBounds.left() <= upperPixelBound) || (mKeyAxis.data()->rangeReversed() && barBounds.right() >= upperPixelBound));
18861 isVisible = ((!mKeyAxis.data()->rangeReversed() && barBounds.left() <= upperPixelBound) || (mKeyAxis.data()->rangeReversed() && barBounds.right() >= upperPixelBound));
19361 else // keyaxis is vertical
18862 else // keyaxis is vertical
19362 isVisible = ((!mKeyAxis.data()->rangeReversed() && barBounds.bottom() >= upperPixelBound) || (mKeyAxis.data()->rangeReversed() && barBounds.top() <= upperPixelBound));
18863 isVisible = ((!mKeyAxis.data()->rangeReversed() && barBounds.bottom() >= upperPixelBound) || (mKeyAxis.data()->rangeReversed() && barBounds.top() <= upperPixelBound));
19363 if (isVisible)
18864 if (isVisible)
19364 upperEnd = it+1;
18865 upperEnd = it+1;
19365 else
18866 else
19366 break;
18867 break;
19367 ++it;
18868 ++it;
19368 }
18869 }
19369 }
18870 }
19370
18871
@@ -19376,33 +18877,33 void QCPBars::getVisibleDataBounds(QCPBa
19376 */
18877 */
19377 QPolygonF QCPBars::getBarPolygon(double key, double value) const
18878 QPolygonF QCPBars::getBarPolygon(double key, double value) const
19378 {
18879 {
19379 QCPAxis *keyAxis = mKeyAxis.data();
18880 QCPAxis *keyAxis = mKeyAxis.data();
19380 QCPAxis *valueAxis = mValueAxis.data();
18881 QCPAxis *valueAxis = mValueAxis.data();
19381 if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return QPolygonF(); }
18882 if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return QPolygonF(); }
19382
18883
19383 QPolygonF result;
18884 QPolygonF result;
19384 double lowerPixelWidth, upperPixelWidth;
18885 double lowerPixelWidth, upperPixelWidth;
19385 getPixelWidth(key, lowerPixelWidth, upperPixelWidth);
18886 getPixelWidth(key, lowerPixelWidth, upperPixelWidth);
19386 double base = getStackedBaseValue(key, value >= 0);
18887 double base = getStackedBaseValue(key, value >= 0);
19387 double basePixel = valueAxis->coordToPixel(base);
18888 double basePixel = valueAxis->coordToPixel(base);
19388 double valuePixel = valueAxis->coordToPixel(base+value);
18889 double valuePixel = valueAxis->coordToPixel(base+value);
19389 double keyPixel = keyAxis->coordToPixel(key);
18890 double keyPixel = keyAxis->coordToPixel(key);
19390 if (mBarsGroup)
18891 if (mBarsGroup)
19391 keyPixel += mBarsGroup->keyPixelOffset(this, key);
18892 keyPixel += mBarsGroup->keyPixelOffset(this, key);
19392 if (keyAxis->orientation() == Qt::Horizontal)
18893 if (keyAxis->orientation() == Qt::Horizontal)
19393 {
18894 {
19394 result << QPointF(keyPixel+lowerPixelWidth, basePixel);
18895 result << QPointF(keyPixel+lowerPixelWidth, basePixel);
19395 result << QPointF(keyPixel+lowerPixelWidth, valuePixel);
18896 result << QPointF(keyPixel+lowerPixelWidth, valuePixel);
19396 result << QPointF(keyPixel+upperPixelWidth, valuePixel);
18897 result << QPointF(keyPixel+upperPixelWidth, valuePixel);
19397 result << QPointF(keyPixel+upperPixelWidth, basePixel);
18898 result << QPointF(keyPixel+upperPixelWidth, basePixel);
19398 } else
18899 } else
19399 {
18900 {
19400 result << QPointF(basePixel, keyPixel+lowerPixelWidth);
18901 result << QPointF(basePixel, keyPixel+lowerPixelWidth);
19401 result << QPointF(valuePixel, keyPixel+lowerPixelWidth);
18902 result << QPointF(valuePixel, keyPixel+lowerPixelWidth);
19402 result << QPointF(valuePixel, keyPixel+upperPixelWidth);
18903 result << QPointF(valuePixel, keyPixel+upperPixelWidth);
19403 result << QPointF(basePixel, keyPixel+upperPixelWidth);
18904 result << QPointF(basePixel, keyPixel+upperPixelWidth);
19404 }
18905 }
19405 return result;
18906 return result;
19406 }
18907 }
19407
18908
19408 /*! \internal
18909 /*! \internal
@@ -19416,44 +18917,44 QPolygonF QCPBars::getBarPolygon(double
19416 */
18917 */
19417 void QCPBars::getPixelWidth(double key, double &lower, double &upper) const
18918 void QCPBars::getPixelWidth(double key, double &lower, double &upper) const
19418 {
18919 {
19419 switch (mWidthType)
18920 switch (mWidthType)
19420 {
18921 {
19421 case wtAbsolute:
18922 case wtAbsolute:
19422 {
18923 {
19423 upper = mWidth*0.5;
18924 upper = mWidth*0.5;
19424 lower = -upper;
18925 lower = -upper;
19425 if (mKeyAxis && (mKeyAxis.data()->rangeReversed() ^ (mKeyAxis.data()->orientation() == Qt::Vertical)))
18926 if (mKeyAxis && (mKeyAxis.data()->rangeReversed() ^ (mKeyAxis.data()->orientation() == Qt::Vertical)))
19426 qSwap(lower, upper);
18927 qSwap(lower, upper);
19427 break;
18928 break;
19428 }
18929 }
19429 case wtAxisRectRatio:
18930 case wtAxisRectRatio:
19430 {
18931 {
19431 if (mKeyAxis && mKeyAxis.data()->axisRect())
18932 if (mKeyAxis && mKeyAxis.data()->axisRect())
19432 {
18933 {
19433 if (mKeyAxis.data()->orientation() == Qt::Horizontal)
18934 if (mKeyAxis.data()->orientation() == Qt::Horizontal)
19434 upper = mKeyAxis.data()->axisRect()->width()*mWidth*0.5;
18935 upper = mKeyAxis.data()->axisRect()->width()*mWidth*0.5;
19435 else
18936 else
19436 upper = mKeyAxis.data()->axisRect()->height()*mWidth*0.5;
18937 upper = mKeyAxis.data()->axisRect()->height()*mWidth*0.5;
19437 lower = -upper;
18938 lower = -upper;
19438 if (mKeyAxis && (mKeyAxis.data()->rangeReversed() ^ (mKeyAxis.data()->orientation() == Qt::Vertical)))
18939 if (mKeyAxis && (mKeyAxis.data()->rangeReversed() ^ (mKeyAxis.data()->orientation() == Qt::Vertical)))
19439 qSwap(lower, upper);
18940 qSwap(lower, upper);
19440 } else
18941 } else
19441 qDebug() << Q_FUNC_INFO << "No key axis or axis rect defined";
18942 qDebug() << Q_FUNC_INFO << "No key axis or axis rect defined";
19442 break;
18943 break;
19443 }
18944 }
19444 case wtPlotCoords:
18945 case wtPlotCoords:
19445 {
18946 {
19446 if (mKeyAxis)
18947 if (mKeyAxis)
19447 {
18948 {
19448 double keyPixel = mKeyAxis.data()->coordToPixel(key);
18949 double keyPixel = mKeyAxis.data()->coordToPixel(key);
19449 upper = mKeyAxis.data()->coordToPixel(key+mWidth*0.5)-keyPixel;
18950 upper = mKeyAxis.data()->coordToPixel(key+mWidth*0.5)-keyPixel;
19450 lower = mKeyAxis.data()->coordToPixel(key-mWidth*0.5)-keyPixel;
18951 lower = mKeyAxis.data()->coordToPixel(key-mWidth*0.5)-keyPixel;
19451 // no need to qSwap(lower, higher) when range reversed, because higher/lower are gained by
18952 // no need to qSwap(lower, higher) when range reversed, because higher/lower are gained by
19452 // coordinate transform which includes range direction
18953 // coordinate transform which includes range direction
19453 } else
18954 } else
19454 qDebug() << Q_FUNC_INFO << "No key axis defined";
18955 qDebug() << Q_FUNC_INFO << "No key axis defined";
19455 break;
18956 break;
19456 }
18957 }
19457 }
18958 }
19458 }
18959 }
19459
18960
@@ -19468,26 +18969,26 void QCPBars::getPixelWidth(double key,
19468 */
18969 */
19469 double QCPBars::getStackedBaseValue(double key, bool positive) const
18970 double QCPBars::getStackedBaseValue(double key, bool positive) const
19470 {
18971 {
19471 if (mBarBelow)
18972 if (mBarBelow)
19472 {
18973 {
19473 double max = 0; // don't use mBaseValue here because only base value of bottom-most bar has meaning in a bar stack
18974 double max = 0; // don't use mBaseValue here because only base value of bottom-most bar has meaning in a bar stack
19474 // find bars of mBarBelow that are approximately at key and find largest one:
18975 // find bars of mBarBelow that are approximately at key and find largest one:
19475 double epsilon = qAbs(key)*1e-6; // should be safe even when changed to use float at some point
18976 double epsilon = qAbs(key)*1e-6; // should be safe even when changed to use float at some point
19476 if (key == 0)
18977 if (key == 0)
19477 epsilon = 1e-6;
18978 epsilon = 1e-6;
19478 QCPBarDataMap::const_iterator it = mBarBelow.data()->mData->lowerBound(key-epsilon);
18979 QCPBarDataMap::const_iterator it = mBarBelow.data()->mData->lowerBound(key-epsilon);
19479 QCPBarDataMap::const_iterator itEnd = mBarBelow.data()->mData->upperBound(key+epsilon);
18980 QCPBarDataMap::const_iterator itEnd = mBarBelow.data()->mData->upperBound(key+epsilon);
19480 while (it != itEnd)
18981 while (it != itEnd)
19481 {
18982 {
19482 if ((positive && it.value().value > max) ||
18983 if ((positive && it.value().value > max) ||
19483 (!positive && it.value().value < max))
18984 (!positive && it.value().value < max))
19484 max = it.value().value;
18985 max = it.value().value;
19485 ++it;
18986 ++it;
19486 }
18987 }
19487 // recurse down the bar-stack to find the total height:
18988 // recurse down the bar-stack to find the total height:
19488 return max + mBarBelow.data()->getStackedBaseValue(key, positive);
18989 return max + mBarBelow.data()->getStackedBaseValue(key, positive);
19489 } else
18990 } else
19490 return mBaseValue;
18991 return mBaseValue;
19491 }
18992 }
19492
18993
19493 /*! \internal
18994 /*! \internal
@@ -19500,115 +19001,115 double QCPBars::getStackedBaseValue(doub
19500 */
19001 */
19501 void QCPBars::connectBars(QCPBars *lower, QCPBars *upper)
19002 void QCPBars::connectBars(QCPBars *lower, QCPBars *upper)
19502 {
19003 {
19503 if (!lower && !upper) return;
19004 if (!lower && !upper) return;
19504
19005
19505 if (!lower) // disconnect upper at bottom
19006 if (!lower) // disconnect upper at bottom
19506 {
19007 {
19507 // disconnect old bar below upper:
19008 // disconnect old bar below upper:
19508 if (upper->mBarBelow && upper->mBarBelow.data()->mBarAbove.data() == upper)
19009 if (upper->mBarBelow && upper->mBarBelow.data()->mBarAbove.data() == upper)
19509 upper->mBarBelow.data()->mBarAbove = 0;
19010 upper->mBarBelow.data()->mBarAbove = 0;
19510 upper->mBarBelow = 0;
19011 upper->mBarBelow = 0;
19511 } else if (!upper) // disconnect lower at top
19012 } else if (!upper) // disconnect lower at top
19512 {
19013 {
19513 // disconnect old bar above lower:
19014 // disconnect old bar above lower:
19514 if (lower->mBarAbove && lower->mBarAbove.data()->mBarBelow.data() == lower)
19015 if (lower->mBarAbove && lower->mBarAbove.data()->mBarBelow.data() == lower)
19515 lower->mBarAbove.data()->mBarBelow = 0;
19016 lower->mBarAbove.data()->mBarBelow = 0;
19516 lower->mBarAbove = 0;
19017 lower->mBarAbove = 0;
19517 } else // connect lower and upper
19018 } else // connect lower and upper
19518 {
19019 {
19519 // disconnect old bar above lower:
19020 // disconnect old bar above lower:
19520 if (lower->mBarAbove && lower->mBarAbove.data()->mBarBelow.data() == lower)
19021 if (lower->mBarAbove && lower->mBarAbove.data()->mBarBelow.data() == lower)
19521 lower->mBarAbove.data()->mBarBelow = 0;
19022 lower->mBarAbove.data()->mBarBelow = 0;
19522 // disconnect old bar below upper:
19023 // disconnect old bar below upper:
19523 if (upper->mBarBelow && upper->mBarBelow.data()->mBarAbove.data() == upper)
19024 if (upper->mBarBelow && upper->mBarBelow.data()->mBarAbove.data() == upper)
19524 upper->mBarBelow.data()->mBarAbove = 0;
19025 upper->mBarBelow.data()->mBarAbove = 0;
19525 lower->mBarAbove = upper;
19026 lower->mBarAbove = upper;
19526 upper->mBarBelow = lower;
19027 upper->mBarBelow = lower;
19527 }
19028 }
19528 }
19029 }
19529
19030
19530 /* inherits documentation from base class */
19031 /* inherits documentation from base class */
19531 QCPRange QCPBars::getKeyRange(bool &foundRange, SignDomain inSignDomain) const
19032 QCPRange QCPBars::getKeyRange(bool &foundRange, SignDomain inSignDomain) const
19532 {
19033 {
19533 QCPRange range;
19034 QCPRange range;
19534 bool haveLower = false;
19035 bool haveLower = false;
19535 bool haveUpper = false;
19036 bool haveUpper = false;
19536
19037
19537 double current;
19038 double current;
19538 QCPBarDataMap::const_iterator it = mData->constBegin();
19039 QCPBarDataMap::const_iterator it = mData->constBegin();
19539 while (it != mData->constEnd())
19040 while (it != mData->constEnd())
19540 {
19041 {
19541 current = it.value().key;
19042 current = it.value().key;
19542 if (inSignDomain == sdBoth || (inSignDomain == sdNegative && current < 0) || (inSignDomain == sdPositive && current > 0))
19043 if (inSignDomain == sdBoth || (inSignDomain == sdNegative && current < 0) || (inSignDomain == sdPositive && current > 0))
19543 {
19044 {
19544 if (current < range.lower || !haveLower)
19045 if (current < range.lower || !haveLower)
19545 {
19046 {
19546 range.lower = current;
19047 range.lower = current;
19547 haveLower = true;
19048 haveLower = true;
19548 }
19049 }
19549 if (current > range.upper || !haveUpper)
19050 if (current > range.upper || !haveUpper)
19550 {
19051 {
19551 range.upper = current;
19052 range.upper = current;
19552 haveUpper = true;
19053 haveUpper = true;
19553 }
19054 }
19554 }
19055 }
19555 ++it;
19056 ++it;
19556 }
19057 }
19557 // determine exact range of bars by including bar width and barsgroup offset:
19058 // determine exact range of bars by including bar width and barsgroup offset:
19558 if (haveLower && mKeyAxis)
19059 if (haveLower && mKeyAxis)
19559 {
19060 {
19560 double lowerPixelWidth, upperPixelWidth, keyPixel;
19061 double lowerPixelWidth, upperPixelWidth, keyPixel;
19561 getPixelWidth(range.lower, lowerPixelWidth, upperPixelWidth);
19062 getPixelWidth(range.lower, lowerPixelWidth, upperPixelWidth);
19562 keyPixel = mKeyAxis.data()->coordToPixel(range.lower) + lowerPixelWidth;
19063 keyPixel = mKeyAxis.data()->coordToPixel(range.lower) + lowerPixelWidth;
19563 if (mBarsGroup)
19064 if (mBarsGroup)
19564 keyPixel += mBarsGroup->keyPixelOffset(this, range.lower);
19065 keyPixel += mBarsGroup->keyPixelOffset(this, range.lower);
19565 range.lower = mKeyAxis.data()->pixelToCoord(keyPixel);
19066 range.lower = mKeyAxis.data()->pixelToCoord(keyPixel);
19566 }
19067 }
19567 if (haveUpper && mKeyAxis)
19068 if (haveUpper && mKeyAxis)
19568 {
19069 {
19569 double lowerPixelWidth, upperPixelWidth, keyPixel;
19070 double lowerPixelWidth, upperPixelWidth, keyPixel;
19570 getPixelWidth(range.upper, lowerPixelWidth, upperPixelWidth);
19071 getPixelWidth(range.upper, lowerPixelWidth, upperPixelWidth);
19571 keyPixel = mKeyAxis.data()->coordToPixel(range.upper) + upperPixelWidth;
19072 keyPixel = mKeyAxis.data()->coordToPixel(range.upper) + upperPixelWidth;
19572 if (mBarsGroup)
19073 if (mBarsGroup)
19573 keyPixel += mBarsGroup->keyPixelOffset(this, range.upper);
19074 keyPixel += mBarsGroup->keyPixelOffset(this, range.upper);
19574 range.upper = mKeyAxis.data()->pixelToCoord(keyPixel);
19075 range.upper = mKeyAxis.data()->pixelToCoord(keyPixel);
19575 }
19076 }
19576 foundRange = haveLower && haveUpper;
19077 foundRange = haveLower && haveUpper;
19577 return range;
19078 return range;
19578 }
19079 }
19579
19080
19580 /* inherits documentation from base class */
19081 /* inherits documentation from base class */
19581 QCPRange QCPBars::getValueRange(bool &foundRange, SignDomain inSignDomain) const
19082 QCPRange QCPBars::getValueRange(bool &foundRange, SignDomain inSignDomain) const
19582 {
19083 {
19583 QCPRange range;
19084 QCPRange range;
19584 range.lower = mBaseValue;
19085 range.lower = mBaseValue;
19585 range.upper = mBaseValue;
19086 range.upper = mBaseValue;
19586 bool haveLower = true; // set to true, because baseValue should always be visible in bar charts
19087 bool haveLower = true; // set to true, because baseValue should always be visible in bar charts
19587 bool haveUpper = true; // set to true, because baseValue should always be visible in bar charts
19088 bool haveUpper = true; // set to true, because baseValue should always be visible in bar charts
19588 double current;
19089 double current;
19589
19090
19590 QCPBarDataMap::const_iterator it = mData->constBegin();
19091 QCPBarDataMap::const_iterator it = mData->constBegin();
19591 while (it != mData->constEnd())
19092 while (it != mData->constEnd())
19592 {
19093 {
19593 current = it.value().value + getStackedBaseValue(it.value().key, it.value().value >= 0);
19094 current = it.value().value + getStackedBaseValue(it.value().key, it.value().value >= 0);
19594 if (inSignDomain == sdBoth || (inSignDomain == sdNegative && current < 0) || (inSignDomain == sdPositive && current > 0))
19095 if (inSignDomain == sdBoth || (inSignDomain == sdNegative && current < 0) || (inSignDomain == sdPositive && current > 0))
19595 {
19096 {
19596 if (current < range.lower || !haveLower)
19097 if (current < range.lower || !haveLower)
19597 {
19098 {
19598 range.lower = current;
19099 range.lower = current;
19599 haveLower = true;
19100 haveLower = true;
19600 }
19101 }
19601 if (current > range.upper || !haveUpper)
19102 if (current > range.upper || !haveUpper)
19602 {
19103 {
19603 range.upper = current;
19104 range.upper = current;
19604 haveUpper = true;
19105 haveUpper = true;
19605 }
19106 }
19606 }
19107 }
19607 ++it;
19108 ++it;
19608 }
19109 }
19609
19110
19610 foundRange = true; // return true because bar charts always have the 0-line visible
19111 foundRange = true; // return true because bar charts always have the 0-line visible
19611 return range;
19112 return range;
19612 }
19113 }
19613
19114
19614
19115
@@ -19679,25 +19180,25 QCPRange QCPBars::getValueRange(bool &fo
19679 QCustomPlot then takes ownership of the statistical box.
19180 QCustomPlot then takes ownership of the statistical box.
19680 */
19181 */
19681 QCPStatisticalBox::QCPStatisticalBox(QCPAxis *keyAxis, QCPAxis *valueAxis) :
19182 QCPStatisticalBox::QCPStatisticalBox(QCPAxis *keyAxis, QCPAxis *valueAxis) :
19682 QCPAbstractPlottable(keyAxis, valueAxis),
19183 QCPAbstractPlottable(keyAxis, valueAxis),
19683 mKey(0),
19184 mKey(0),
19684 mMinimum(0),
19185 mMinimum(0),
19685 mLowerQuartile(0),
19186 mLowerQuartile(0),
19686 mMedian(0),
19187 mMedian(0),
19687 mUpperQuartile(0),
19188 mUpperQuartile(0),
19688 mMaximum(0)
19189 mMaximum(0)
19689 {
19190 {
19690 setOutlierStyle(QCPScatterStyle(QCPScatterStyle::ssCircle, Qt::blue, 6));
19191 setOutlierStyle(QCPScatterStyle(QCPScatterStyle::ssCircle, Qt::blue, 6));
19691 setWhiskerWidth(0.2);
19192 setWhiskerWidth(0.2);
19692 setWidth(0.5);
19193 setWidth(0.5);
19693
19194
19694 setPen(QPen(Qt::black));
19195 setPen(QPen(Qt::black));
19695 setSelectedPen(QPen(Qt::blue, 2.5));
19196 setSelectedPen(QPen(Qt::blue, 2.5));
19696 setMedianPen(QPen(Qt::black, 3, Qt::SolidLine, Qt::FlatCap));
19197 setMedianPen(QPen(Qt::black, 3, Qt::SolidLine, Qt::FlatCap));
19697 setWhiskerPen(QPen(Qt::black, 0, Qt::DashLine, Qt::FlatCap));
19198 setWhiskerPen(QPen(Qt::black, 0, Qt::DashLine, Qt::FlatCap));
19698 setWhiskerBarPen(QPen(Qt::black));
19199 setWhiskerBarPen(QPen(Qt::black));
19699 setBrush(Qt::NoBrush);
19200 setBrush(Qt::NoBrush);
19700 setSelectedBrush(Qt::NoBrush);
19201 setSelectedBrush(Qt::NoBrush);
19701 }
19202 }
19702
19203
19703 /*!
19204 /*!
@@ -19705,7 +19206,7 QCPStatisticalBox::QCPStatisticalBox(QCP
19705 */
19206 */
19706 void QCPStatisticalBox::setKey(double key)
19207 void QCPStatisticalBox::setKey(double key)
19707 {
19208 {
19708 mKey = key;
19209 mKey = key;
19709 }
19210 }
19710
19211
19711 /*!
19212 /*!
@@ -19716,7 +19217,7 void QCPStatisticalBox::setKey(double ke
19716 */
19217 */
19717 void QCPStatisticalBox::setMinimum(double value)
19218 void QCPStatisticalBox::setMinimum(double value)
19718 {
19219 {
19719 mMinimum = value;
19220 mMinimum = value;
19720 }
19221 }
19721
19222
19722 /*!
19223 /*!
@@ -19728,7 +19229,7 void QCPStatisticalBox::setMinimum(doubl
19728 */
19229 */
19729 void QCPStatisticalBox::setLowerQuartile(double value)
19230 void QCPStatisticalBox::setLowerQuartile(double value)
19730 {
19231 {
19731 mLowerQuartile = value;
19232 mLowerQuartile = value;
19732 }
19233 }
19733
19234
19734 /*!
19235 /*!
@@ -19740,7 +19241,7 void QCPStatisticalBox::setLowerQuartile
19740 */
19241 */
19741 void QCPStatisticalBox::setMedian(double value)
19242 void QCPStatisticalBox::setMedian(double value)
19742 {
19243 {
19743 mMedian = value;
19244 mMedian = value;
19744 }
19245 }
19745
19246
19746 /*!
19247 /*!
@@ -19752,7 +19253,7 void QCPStatisticalBox::setMedian(double
19752 */
19253 */
19753 void QCPStatisticalBox::setUpperQuartile(double value)
19254 void QCPStatisticalBox::setUpperQuartile(double value)
19754 {
19255 {
19755 mUpperQuartile = value;
19256 mUpperQuartile = value;
19756 }
19257 }
19757
19258
19758 /*!
19259 /*!
@@ -19763,7 +19264,7 void QCPStatisticalBox::setUpperQuartile
19763 */
19264 */
19764 void QCPStatisticalBox::setMaximum(double value)
19265 void QCPStatisticalBox::setMaximum(double value)
19765 {
19266 {
19766 mMaximum = value;
19267 mMaximum = value;
19767 }
19268 }
19768
19269
19769 /*!
19270 /*!
@@ -19775,7 +19276,7 void QCPStatisticalBox::setMaximum(doubl
19775 */
19276 */
19776 void QCPStatisticalBox::setOutliers(const QVector<double> &values)
19277 void QCPStatisticalBox::setOutliers(const QVector<double> &values)
19777 {
19278 {
19778 mOutliers = values;
19279 mOutliers = values;
19779 }
19280 }
19780
19281
19781 /*!
19282 /*!
@@ -19785,12 +19286,12 void QCPStatisticalBox::setOutliers(cons
19785 */
19286 */
19786 void QCPStatisticalBox::setData(double key, double minimum, double lowerQuartile, double median, double upperQuartile, double maximum)
19287 void QCPStatisticalBox::setData(double key, double minimum, double lowerQuartile, double median, double upperQuartile, double maximum)
19787 {
19288 {
19788 setKey(key);
19289 setKey(key);
19789 setMinimum(minimum);
19290 setMinimum(minimum);
19790 setLowerQuartile(lowerQuartile);
19291 setLowerQuartile(lowerQuartile);
19791 setMedian(median);
19292 setMedian(median);
19792 setUpperQuartile(upperQuartile);
19293 setUpperQuartile(upperQuartile);
19793 setMaximum(maximum);
19294 setMaximum(maximum);
19794 }
19295 }
19795
19296
19796 /*!
19297 /*!
@@ -19800,7 +19301,7 void QCPStatisticalBox::setData(double k
19800 */
19301 */
19801 void QCPStatisticalBox::setWidth(double width)
19302 void QCPStatisticalBox::setWidth(double width)
19802 {
19303 {
19803 mWidth = width;
19304 mWidth = width;
19804 }
19305 }
19805
19306
19806 /*!
19307 /*!
@@ -19810,7 +19311,7 void QCPStatisticalBox::setWidth(double
19810 */
19311 */
19811 void QCPStatisticalBox::setWhiskerWidth(double width)
19312 void QCPStatisticalBox::setWhiskerWidth(double width)
19812 {
19313 {
19813 mWhiskerWidth = width;
19314 mWhiskerWidth = width;
19814 }
19315 }
19815
19316
19816 /*!
19317 /*!
@@ -19823,7 +19324,7 void QCPStatisticalBox::setWhiskerWidth(
19823 */
19324 */
19824 void QCPStatisticalBox::setWhiskerPen(const QPen &pen)
19325 void QCPStatisticalBox::setWhiskerPen(const QPen &pen)
19825 {
19326 {
19826 mWhiskerPen = pen;
19327 mWhiskerPen = pen;
19827 }
19328 }
19828
19329
19829 /*!
19330 /*!
@@ -19834,7 +19335,7 void QCPStatisticalBox::setWhiskerPen(co
19834 */
19335 */
19835 void QCPStatisticalBox::setWhiskerBarPen(const QPen &pen)
19336 void QCPStatisticalBox::setWhiskerBarPen(const QPen &pen)
19836 {
19337 {
19837 mWhiskerBarPen = pen;
19338 mWhiskerBarPen = pen;
19838 }
19339 }
19839
19340
19840 /*!
19341 /*!
@@ -19842,7 +19343,7 void QCPStatisticalBox::setWhiskerBarPen
19842 */
19343 */
19843 void QCPStatisticalBox::setMedianPen(const QPen &pen)
19344 void QCPStatisticalBox::setMedianPen(const QPen &pen)
19844 {
19345 {
19845 mMedianPen = pen;
19346 mMedianPen = pen;
19846 }
19347 }
19847
19348
19848 /*!
19349 /*!
@@ -19852,84 +19353,84 void QCPStatisticalBox::setMedianPen(con
19852 */
19353 */
19853 void QCPStatisticalBox::setOutlierStyle(const QCPScatterStyle &style)
19354 void QCPStatisticalBox::setOutlierStyle(const QCPScatterStyle &style)
19854 {
19355 {
19855 mOutlierStyle = style;
19356 mOutlierStyle = style;
19856 }
19357 }
19857
19358
19858 /* inherits documentation from base class */
19359 /* inherits documentation from base class */
19859 void QCPStatisticalBox::clearData()
19360 void QCPStatisticalBox::clearData()
19860 {
19361 {
19861 setOutliers(QVector<double>());
19362 setOutliers(QVector<double>());
19862 setKey(0);
19363 setKey(0);
19863 setMinimum(0);
19364 setMinimum(0);
19864 setLowerQuartile(0);
19365 setLowerQuartile(0);
19865 setMedian(0);
19366 setMedian(0);
19866 setUpperQuartile(0);
19367 setUpperQuartile(0);
19867 setMaximum(0);
19368 setMaximum(0);
19868 }
19369 }
19869
19370
19870 /* inherits documentation from base class */
19371 /* inherits documentation from base class */
19871 double QCPStatisticalBox::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
19372 double QCPStatisticalBox::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
19872 {
19373 {
19873 Q_UNUSED(details)
19374 Q_UNUSED(details)
19874 if (onlySelectable && !mSelectable)
19375 if (onlySelectable && !mSelectable)
19376 return -1;
19377 if (!mKeyAxis || !mValueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return -1; }
19378
19379 if (mKeyAxis.data()->axisRect()->rect().contains(pos.toPoint()))
19380 {
19381 double posKey, posValue;
19382 pixelsToCoords(pos, posKey, posValue);
19383 // quartile box:
19384 QCPRange keyRange(mKey-mWidth*0.5, mKey+mWidth*0.5);
19385 QCPRange valueRange(mLowerQuartile, mUpperQuartile);
19386 if (keyRange.contains(posKey) && valueRange.contains(posValue))
19387 return mParentPlot->selectionTolerance()*0.99;
19388
19389 // min/max whiskers:
19390 if (QCPRange(mMinimum, mMaximum).contains(posValue))
19391 return qAbs(mKeyAxis.data()->coordToPixel(mKey)-mKeyAxis.data()->coordToPixel(posKey));
19392 }
19875 return -1;
19393 return -1;
19876 if (!mKeyAxis || !mValueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return -1; }
19877
19878 if (mKeyAxis.data()->axisRect()->rect().contains(pos.toPoint()))
19879 {
19880 double posKey, posValue;
19881 pixelsToCoords(pos, posKey, posValue);
19882 // quartile box:
19883 QCPRange keyRange(mKey-mWidth*0.5, mKey+mWidth*0.5);
19884 QCPRange valueRange(mLowerQuartile, mUpperQuartile);
19885 if (keyRange.contains(posKey) && valueRange.contains(posValue))
19886 return mParentPlot->selectionTolerance()*0.99;
19887
19888 // min/max whiskers:
19889 if (QCPRange(mMinimum, mMaximum).contains(posValue))
19890 return qAbs(mKeyAxis.data()->coordToPixel(mKey)-mKeyAxis.data()->coordToPixel(posKey));
19891 }
19892 return -1;
19893 }
19394 }
19894
19395
19895 /* inherits documentation from base class */
19396 /* inherits documentation from base class */
19896 void QCPStatisticalBox::draw(QCPPainter *painter)
19397 void QCPStatisticalBox::draw(QCPPainter *painter)
19897 {
19398 {
19898 if (!mKeyAxis || !mValueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
19399 if (!mKeyAxis || !mValueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
19899
19400
19900 // check data validity if flag set:
19401 // check data validity if flag set:
19901 #ifdef QCUSTOMPLOT_CHECK_DATA
19402 #ifdef QCUSTOMPLOT_CHECK_DATA
19902 if (QCP::isInvalidData(mKey, mMedian) ||
19403 if (QCP::isInvalidData(mKey, mMedian) ||
19903 QCP::isInvalidData(mLowerQuartile, mUpperQuartile) ||
19404 QCP::isInvalidData(mLowerQuartile, mUpperQuartile) ||
19904 QCP::isInvalidData(mMinimum, mMaximum))
19405 QCP::isInvalidData(mMinimum, mMaximum))
19905 qDebug() << Q_FUNC_INFO << "Data point at" << mKey << "of drawn range has invalid data." << "Plottable name:" << name();
19406 qDebug() << Q_FUNC_INFO << "Data point at" << mKey << "of drawn range has invalid data." << "Plottable name:" << name();
19906 for (int i=0; i<mOutliers.size(); ++i)
19407 for (int i=0; i<mOutliers.size(); ++i)
19907 if (QCP::isInvalidData(mOutliers.at(i)))
19408 if (QCP::isInvalidData(mOutliers.at(i)))
19908 qDebug() << Q_FUNC_INFO << "Data point outlier at" << mKey << "of drawn range invalid." << "Plottable name:" << name();
19409 qDebug() << Q_FUNC_INFO << "Data point outlier at" << mKey << "of drawn range invalid." << "Plottable name:" << name();
19909 #endif
19410 #endif
19910
19411
19911 QRectF quartileBox;
19412 QRectF quartileBox;
19912 drawQuartileBox(painter, &quartileBox);
19413 drawQuartileBox(painter, &quartileBox);
19913
19414
19914 painter->save();
19415 painter->save();
19915 painter->setClipRect(quartileBox, Qt::IntersectClip);
19416 painter->setClipRect(quartileBox, Qt::IntersectClip);
19916 drawMedian(painter);
19417 drawMedian(painter);
19917 painter->restore();
19418 painter->restore();
19918
19419
19919 drawWhiskers(painter);
19420 drawWhiskers(painter);
19920 drawOutliers(painter);
19421 drawOutliers(painter);
19921 }
19422 }
19922
19423
19923 /* inherits documentation from base class */
19424 /* inherits documentation from base class */
19924 void QCPStatisticalBox::drawLegendIcon(QCPPainter *painter, const QRectF &rect) const
19425 void QCPStatisticalBox::drawLegendIcon(QCPPainter *painter, const QRectF &rect) const
19925 {
19426 {
19926 // draw filled rect:
19427 // draw filled rect:
19927 applyDefaultAntialiasingHint(painter);
19428 applyDefaultAntialiasingHint(painter);
19928 painter->setPen(mPen);
19429 painter->setPen(mPen);
19929 painter->setBrush(mBrush);
19430 painter->setBrush(mBrush);
19930 QRectF r = QRectF(0, 0, rect.width()*0.67, rect.height()*0.67);
19431 QRectF r = QRectF(0, 0, rect.width()*0.67, rect.height()*0.67);
19931 r.moveCenter(rect.center());
19432 r.moveCenter(rect.center());
19932 painter->drawRect(r);
19433 painter->drawRect(r);
19933 }
19434 }
19934
19435
19935 /*! \internal
19436 /*! \internal
@@ -19940,15 +19441,15 void QCPStatisticalBox::drawLegendIcon(Q
19940 */
19441 */
19941 void QCPStatisticalBox::drawQuartileBox(QCPPainter *painter, QRectF *quartileBox) const
19442 void QCPStatisticalBox::drawQuartileBox(QCPPainter *painter, QRectF *quartileBox) const
19942 {
19443 {
19943 QRectF box;
19444 QRectF box;
19944 box.setTopLeft(coordsToPixels(mKey-mWidth*0.5, mUpperQuartile));
19445 box.setTopLeft(coordsToPixels(mKey-mWidth*0.5, mUpperQuartile));
19945 box.setBottomRight(coordsToPixels(mKey+mWidth*0.5, mLowerQuartile));
19446 box.setBottomRight(coordsToPixels(mKey+mWidth*0.5, mLowerQuartile));
19946 applyDefaultAntialiasingHint(painter);
19447 applyDefaultAntialiasingHint(painter);
19947 painter->setPen(mainPen());
19448 painter->setPen(mainPen());
19948 painter->setBrush(mainBrush());
19449 painter->setBrush(mainBrush());
19949 painter->drawRect(box);
19450 painter->drawRect(box);
19950 if (quartileBox)
19451 if (quartileBox)
19951 *quartileBox = box;
19452 *quartileBox = box;
19952 }
19453 }
19953
19454
19954 /*! \internal
19455 /*! \internal
@@ -19957,12 +19458,12 void QCPStatisticalBox::drawQuartileBox(
19957 */
19458 */
19958 void QCPStatisticalBox::drawMedian(QCPPainter *painter) const
19459 void QCPStatisticalBox::drawMedian(QCPPainter *painter) const
19959 {
19460 {
19960 QLineF medianLine;
19461 QLineF medianLine;
19961 medianLine.setP1(coordsToPixels(mKey-mWidth*0.5, mMedian));
19462 medianLine.setP1(coordsToPixels(mKey-mWidth*0.5, mMedian));
19962 medianLine.setP2(coordsToPixels(mKey+mWidth*0.5, mMedian));
19463 medianLine.setP2(coordsToPixels(mKey+mWidth*0.5, mMedian));
19963 applyDefaultAntialiasingHint(painter);
19464 applyDefaultAntialiasingHint(painter);
19964 painter->setPen(mMedianPen);
19465 painter->setPen(mMedianPen);
19965 painter->drawLine(medianLine);
19466 painter->drawLine(medianLine);
19966 }
19467 }
19967
19468
19968 /*! \internal
19469 /*! \internal
@@ -19971,18 +19472,18 void QCPStatisticalBox::drawMedian(QCPPa
19971 */
19472 */
19972 void QCPStatisticalBox::drawWhiskers(QCPPainter *painter) const
19473 void QCPStatisticalBox::drawWhiskers(QCPPainter *painter) const
19973 {
19474 {
19974 QLineF backboneMin, backboneMax, barMin, barMax;
19475 QLineF backboneMin, backboneMax, barMin, barMax;
19975 backboneMax.setPoints(coordsToPixels(mKey, mUpperQuartile), coordsToPixels(mKey, mMaximum));
19476 backboneMax.setPoints(coordsToPixels(mKey, mUpperQuartile), coordsToPixels(mKey, mMaximum));
19976 backboneMin.setPoints(coordsToPixels(mKey, mLowerQuartile), coordsToPixels(mKey, mMinimum));
19477 backboneMin.setPoints(coordsToPixels(mKey, mLowerQuartile), coordsToPixels(mKey, mMinimum));
19977 barMax.setPoints(coordsToPixels(mKey-mWhiskerWidth*0.5, mMaximum), coordsToPixels(mKey+mWhiskerWidth*0.5, mMaximum));
19478 barMax.setPoints(coordsToPixels(mKey-mWhiskerWidth*0.5, mMaximum), coordsToPixels(mKey+mWhiskerWidth*0.5, mMaximum));
19978 barMin.setPoints(coordsToPixels(mKey-mWhiskerWidth*0.5, mMinimum), coordsToPixels(mKey+mWhiskerWidth*0.5, mMinimum));
19479 barMin.setPoints(coordsToPixels(mKey-mWhiskerWidth*0.5, mMinimum), coordsToPixels(mKey+mWhiskerWidth*0.5, mMinimum));
19979 applyErrorBarsAntialiasingHint(painter);
19480 applyErrorBarsAntialiasingHint(painter);
19980 painter->setPen(mWhiskerPen);
19481 painter->setPen(mWhiskerPen);
19981 painter->drawLine(backboneMin);
19482 painter->drawLine(backboneMin);
19982 painter->drawLine(backboneMax);
19483 painter->drawLine(backboneMax);
19983 painter->setPen(mWhiskerBarPen);
19484 painter->setPen(mWhiskerBarPen);
19984 painter->drawLine(barMin);
19485 painter->drawLine(barMin);
19985 painter->drawLine(barMax);
19486 painter->drawLine(barMax);
19986 }
19487 }
19987
19488
19988 /*! \internal
19489 /*! \internal
@@ -19991,85 +19492,85 void QCPStatisticalBox::drawWhiskers(QCP
19991 */
19492 */
19992 void QCPStatisticalBox::drawOutliers(QCPPainter *painter) const
19493 void QCPStatisticalBox::drawOutliers(QCPPainter *painter) const
19993 {
19494 {
19994 applyScattersAntialiasingHint(painter);
19495 applyScattersAntialiasingHint(painter);
19995 mOutlierStyle.applyTo(painter, mPen);
19496 mOutlierStyle.applyTo(painter, mPen);
19996 for (int i=0; i<mOutliers.size(); ++i)
19497 for (int i=0; i<mOutliers.size(); ++i)
19997 mOutlierStyle.drawShape(painter, coordsToPixels(mKey, mOutliers.at(i)));
19498 mOutlierStyle.drawShape(painter, coordsToPixels(mKey, mOutliers.at(i)));
19998 }
19499 }
19999
19500
20000 /* inherits documentation from base class */
19501 /* inherits documentation from base class */
20001 QCPRange QCPStatisticalBox::getKeyRange(bool &foundRange, SignDomain inSignDomain) const
19502 QCPRange QCPStatisticalBox::getKeyRange(bool &foundRange, SignDomain inSignDomain) const
20002 {
19503 {
20003 foundRange = true;
19504 foundRange = true;
20004 if (inSignDomain == sdBoth)
19505 if (inSignDomain == sdBoth)
20005 {
19506 {
20006 return QCPRange(mKey-mWidth*0.5, mKey+mWidth*0.5);
19507 return QCPRange(mKey-mWidth*0.5, mKey+mWidth*0.5);
20007 } else if (inSignDomain == sdNegative)
19508 } else if (inSignDomain == sdNegative)
20008 {
19509 {
20009 if (mKey+mWidth*0.5 < 0)
19510 if (mKey+mWidth*0.5 < 0)
20010 return QCPRange(mKey-mWidth*0.5, mKey+mWidth*0.5);
19511 return QCPRange(mKey-mWidth*0.5, mKey+mWidth*0.5);
20011 else if (mKey < 0)
19512 else if (mKey < 0)
20012 return QCPRange(mKey-mWidth*0.5, mKey);
19513 return QCPRange(mKey-mWidth*0.5, mKey);
20013 else
19514 else
20014 {
19515 {
20015 foundRange = false;
19516 foundRange = false;
20016 return QCPRange();
19517 return QCPRange();
20017 }
19518 }
20018 } else if (inSignDomain == sdPositive)
19519 } else if (inSignDomain == sdPositive)
20019 {
19520 {
20020 if (mKey-mWidth*0.5 > 0)
19521 if (mKey-mWidth*0.5 > 0)
20021 return QCPRange(mKey-mWidth*0.5, mKey+mWidth*0.5);
19522 return QCPRange(mKey-mWidth*0.5, mKey+mWidth*0.5);
20022 else if (mKey > 0)
19523 else if (mKey > 0)
20023 return QCPRange(mKey, mKey+mWidth*0.5);
19524 return QCPRange(mKey, mKey+mWidth*0.5);
20024 else
19525 else
20025 {
19526 {
20026 foundRange = false;
19527 foundRange = false;
20027 return QCPRange();
19528 return QCPRange();
20028 }
19529 }
20029 }
19530 }
20030 foundRange = false;
19531 foundRange = false;
20031 return QCPRange();
19532 return QCPRange();
20032 }
19533 }
20033
19534
20034 /* inherits documentation from base class */
19535 /* inherits documentation from base class */
20035 QCPRange QCPStatisticalBox::getValueRange(bool &foundRange, SignDomain inSignDomain) const
19536 QCPRange QCPStatisticalBox::getValueRange(bool &foundRange, SignDomain inSignDomain) const
20036 {
19537 {
20037 QVector<double> values; // values that must be considered (i.e. all outliers and the five box-parameters)
19538 QVector<double> values; // values that must be considered (i.e. all outliers and the five box-parameters)
20038 values.reserve(mOutliers.size() + 5);
19539 values.reserve(mOutliers.size() + 5);
20039 values << mMaximum << mUpperQuartile << mMedian << mLowerQuartile << mMinimum;
19540 values << mMaximum << mUpperQuartile << mMedian << mLowerQuartile << mMinimum;
20040 values << mOutliers;
19541 values << mOutliers;
20041 // go through values and find the ones in legal range:
19542 // go through values and find the ones in legal range:
20042 bool haveUpper = false;
19543 bool haveUpper = false;
20043 bool haveLower = false;
19544 bool haveLower = false;
20044 double upper = 0;
19545 double upper = 0;
20045 double lower = 0;
19546 double lower = 0;
20046 for (int i=0; i<values.size(); ++i)
19547 for (int i=0; i<values.size(); ++i)
20047 {
19548 {
20048 if ((inSignDomain == sdNegative && values.at(i) < 0) ||
19549 if ((inSignDomain == sdNegative && values.at(i) < 0) ||
20049 (inSignDomain == sdPositive && values.at(i) > 0) ||
19550 (inSignDomain == sdPositive && values.at(i) > 0) ||
20050 (inSignDomain == sdBoth))
19551 (inSignDomain == sdBoth))
20051 {
19552 {
20052 if (values.at(i) > upper || !haveUpper)
19553 if (values.at(i) > upper || !haveUpper)
20053 {
19554 {
20054 upper = values.at(i);
19555 upper = values.at(i);
20055 haveUpper = true;
19556 haveUpper = true;
20056 }
19557 }
20057 if (values.at(i) < lower || !haveLower)
19558 if (values.at(i) < lower || !haveLower)
20058 {
19559 {
20059 lower = values.at(i);
19560 lower = values.at(i);
20060 haveLower = true;
19561 haveLower = true;
20061 }
19562 }
20062 }
19563 }
20063 }
19564 }
20064 // return the bounds if we found some sensible values:
19565 // return the bounds if we found some sensible values:
20065 if (haveLower && haveUpper)
19566 if (haveLower && haveUpper)
20066 {
19567 {
20067 foundRange = true;
19568 foundRange = true;
20068 return QCPRange(lower, upper);
19569 return QCPRange(lower, upper);
20069 } else // might happen if all values are in other sign domain
19570 } else // might happen if all values are in other sign domain
20070 {
19571 {
20071 foundRange = false;
19572 foundRange = false;
20072 return QCPRange();
19573 return QCPRange();
20073 }
19574 }
20074 }
19575 }
20075
19576
@@ -20124,35 +19625,35 QCPRange QCPStatisticalBox::getValueRang
20124 \see setSize, setKeySize, setValueSize, setRange, setKeyRange, setValueRange
19625 \see setSize, setKeySize, setValueSize, setRange, setKeyRange, setValueRange
20125 */
19626 */
20126 QCPColorMapData::QCPColorMapData(int keySize, int valueSize, const QCPRange &keyRange, const QCPRange &valueRange) :
19627 QCPColorMapData::QCPColorMapData(int keySize, int valueSize, const QCPRange &keyRange, const QCPRange &valueRange) :
20127 mKeySize(0),
19628 mKeySize(0),
20128 mValueSize(0),
19629 mValueSize(0),
20129 mKeyRange(keyRange),
19630 mKeyRange(keyRange),
20130 mValueRange(valueRange),
19631 mValueRange(valueRange),
20131 mIsEmpty(true),
19632 mIsEmpty(true),
20132 mData(0),
19633 mData(0),
20133 mDataModified(true)
19634 mDataModified(true)
20134 {
19635 {
20135 setSize(keySize, valueSize);
19636 setSize(keySize, valueSize);
20136 fill(0);
19637 fill(0);
20137 }
19638 }
20138
19639
20139 QCPColorMapData::~QCPColorMapData()
19640 QCPColorMapData::~QCPColorMapData()
20140 {
19641 {
20141 if (mData)
19642 if (mData)
20142 delete[] mData;
19643 delete[] mData;
20143 }
19644 }
20144
19645
20145 /*!
19646 /*!
20146 Constructs a new QCPColorMapData instance copying the data and range of \a other.
19647 Constructs a new QCPColorMapData instance copying the data and range of \a other.
20147 */
19648 */
20148 QCPColorMapData::QCPColorMapData(const QCPColorMapData &other) :
19649 QCPColorMapData::QCPColorMapData(const QCPColorMapData &other) :
20149 mKeySize(0),
19650 mKeySize(0),
20150 mValueSize(0),
19651 mValueSize(0),
20151 mIsEmpty(true),
19652 mIsEmpty(true),
20152 mData(0),
19653 mData(0),
20153 mDataModified(true)
19654 mDataModified(true)
20154 {
19655 {
20155 *this = other;
19656 *this = other;
20156 }
19657 }
20157
19658
20158 /*!
19659 /*!
@@ -20160,38 +19661,38 QCPColorMapData::QCPColorMapData(const Q
20160 */
19661 */
20161 QCPColorMapData &QCPColorMapData::operator=(const QCPColorMapData &other)
19662 QCPColorMapData &QCPColorMapData::operator=(const QCPColorMapData &other)
20162 {
19663 {
20163 if (&other != this)
19664 if (&other != this)
20164 {
19665 {
20165 const int keySize = other.keySize();
19666 const int keySize = other.keySize();
20166 const int valueSize = other.valueSize();
19667 const int valueSize = other.valueSize();
20167 setSize(keySize, valueSize);
19668 setSize(keySize, valueSize);
20168 setRange(other.keyRange(), other.valueRange());
19669 setRange(other.keyRange(), other.valueRange());
20169 if (!mIsEmpty)
19670 if (!mIsEmpty)
20170 memcpy(mData, other.mData, sizeof(mData[0])*keySize*valueSize);
19671 memcpy(mData, other.mData, sizeof(mData[0])*keySize*valueSize);
20171 mDataBounds = other.mDataBounds;
19672 mDataBounds = other.mDataBounds;
20172 mDataModified = true;
19673 mDataModified = true;
20173 }
19674 }
20174 return *this;
19675 return *this;
20175 }
19676 }
20176
19677
20177 /* undocumented getter */
19678 /* undocumented getter */
20178 double QCPColorMapData::data(double key, double value)
19679 double QCPColorMapData::data(double key, double value)
20179 {
19680 {
20180 int keyCell = (key-mKeyRange.lower)/(mKeyRange.upper-mKeyRange.lower)*(mKeySize-1)+0.5;
19681 int keyCell = (key-mKeyRange.lower)/(mKeyRange.upper-mKeyRange.lower)*(mKeySize-1)+0.5;
20181 int valueCell = (value-mValueRange.lower)/(mValueRange.upper-mValueRange.lower)*(mValueSize-1)+0.5;
19682 int valueCell = (value-mValueRange.lower)/(mValueRange.upper-mValueRange.lower)*(mValueSize-1)+0.5;
20182 if (keyCell >= 0 && keyCell < mKeySize && valueCell >= 0 && valueCell < mValueSize)
19683 if (keyCell >= 0 && keyCell < mKeySize && valueCell >= 0 && valueCell < mValueSize)
20183 return mData[valueCell*mKeySize + keyCell];
19684 return mData[valueCell*mKeySize + keyCell];
20184 else
19685 else
20185 return 0;
19686 return 0;
20186 }
19687 }
20187
19688
20188 /* undocumented getter */
19689 /* undocumented getter */
20189 double QCPColorMapData::cell(int keyIndex, int valueIndex)
19690 double QCPColorMapData::cell(int keyIndex, int valueIndex)
20190 {
19691 {
20191 if (keyIndex >= 0 && keyIndex < mKeySize && valueIndex >= 0 && valueIndex < mValueSize)
19692 if (keyIndex >= 0 && keyIndex < mKeySize && valueIndex >= 0 && valueIndex < mValueSize)
20192 return mData[valueIndex*mKeySize + keyIndex];
19693 return mData[valueIndex*mKeySize + keyIndex];
20193 else
19694 else
20194 return 0;
19695 return 0;
20195 }
19696 }
20196
19697
20197 /*!
19698 /*!
@@ -20208,29 +19709,29 double QCPColorMapData::cell(int keyInde
20208 */
19709 */
20209 void QCPColorMapData::setSize(int keySize, int valueSize)
19710 void QCPColorMapData::setSize(int keySize, int valueSize)
20210 {
19711 {
20211 if (keySize != mKeySize || valueSize != mValueSize)
19712 if (keySize != mKeySize || valueSize != mValueSize)
20212 {
19713 {
20213 mKeySize = keySize;
19714 mKeySize = keySize;
20214 mValueSize = valueSize;
19715 mValueSize = valueSize;
20215 if (mData)
19716 if (mData)
20216 delete[] mData;
19717 delete[] mData;
20217 mIsEmpty = mKeySize == 0 || mValueSize == 0;
19718 mIsEmpty = mKeySize == 0 || mValueSize == 0;
20218 if (!mIsEmpty)
19719 if (!mIsEmpty)
20219 {
19720 {
20220 #ifdef __EXCEPTIONS
19721 #ifdef __EXCEPTIONS
20221 try { // 2D arrays get memory intensive fast. So if the allocation fails, at least output debug message
19722 try { // 2D arrays get memory intensive fast. So if the allocation fails, at least output debug message
20222 #endif
19723 #endif
20223 mData = new double[mKeySize*mValueSize];
19724 mData = new double[mKeySize*mValueSize];
20224 #ifdef __EXCEPTIONS
19725 #ifdef __EXCEPTIONS
20225 } catch (...) { mData = 0; }
19726 } catch (...) { mData = 0; }
20226 #endif
19727 #endif
20227 if (mData)
19728 if (mData)
20228 fill(0);
19729 fill(0);
20229 else
19730 else
20230 qDebug() << Q_FUNC_INFO << "out of memory for data dimensions "<< mKeySize << "*" << mValueSize;
19731 qDebug() << Q_FUNC_INFO << "out of memory for data dimensions "<< mKeySize << "*" << mValueSize;
20231 } else
19732 } else
20232 mData = 0;
19733 mData = 0;
20233 mDataModified = true;
19734 mDataModified = true;
20234 }
19735 }
20235 }
19736 }
20236
19737
@@ -20246,7 +19747,7 void QCPColorMapData::setSize(int keySiz
20246 */
19747 */
20247 void QCPColorMapData::setKeySize(int keySize)
19748 void QCPColorMapData::setKeySize(int keySize)
20248 {
19749 {
20249 setSize(keySize, mValueSize);
19750 setSize(keySize, mValueSize);
20250 }
19751 }
20251
19752
20252 /*!
19753 /*!
@@ -20261,7 +19762,7 void QCPColorMapData::setKeySize(int key
20261 */
19762 */
20262 void QCPColorMapData::setValueSize(int valueSize)
19763 void QCPColorMapData::setValueSize(int valueSize)
20263 {
19764 {
20264 setSize(mKeySize, valueSize);
19765 setSize(mKeySize, valueSize);
20265 }
19766 }
20266
19767
20267 /*!
19768 /*!
@@ -20276,8 +19777,8 void QCPColorMapData::setValueSize(int v
20276 */
19777 */
20277 void QCPColorMapData::setRange(const QCPRange &keyRange, const QCPRange &valueRange)
19778 void QCPColorMapData::setRange(const QCPRange &keyRange, const QCPRange &valueRange)
20278 {
19779 {
20279 setKeyRange(keyRange);
19780 setKeyRange(keyRange);
20280 setValueRange(valueRange);
19781 setValueRange(valueRange);
20281 }
19782 }
20282
19783
20283 /*!
19784 /*!
@@ -20292,7 +19793,7 void QCPColorMapData::setRange(const QCP
20292 */
19793 */
20293 void QCPColorMapData::setKeyRange(const QCPRange &keyRange)
19794 void QCPColorMapData::setKeyRange(const QCPRange &keyRange)
20294 {
19795 {
20295 mKeyRange = keyRange;
19796 mKeyRange = keyRange;
20296 }
19797 }
20297
19798
20298 /*!
19799 /*!
@@ -20307,7 +19808,7 void QCPColorMapData::setKeyRange(const
20307 */
19808 */
20308 void QCPColorMapData::setValueRange(const QCPRange &valueRange)
19809 void QCPColorMapData::setValueRange(const QCPRange &valueRange)
20309 {
19810 {
20310 mValueRange = valueRange;
19811 mValueRange = valueRange;
20311 }
19812 }
20312
19813
20313 /*!
19814 /*!
@@ -20318,16 +19819,16 void QCPColorMapData::setValueRange(cons
20318 */
19819 */
20319 void QCPColorMapData::setData(double key, double value, double z)
19820 void QCPColorMapData::setData(double key, double value, double z)
20320 {
19821 {
20321 int keyCell = (key-mKeyRange.lower)/(mKeyRange.upper-mKeyRange.lower)*(mKeySize-1)+0.5;
19822 int keyCell = (key-mKeyRange.lower)/(mKeyRange.upper-mKeyRange.lower)*(mKeySize-1)+0.5;
20322 int valueCell = (value-mValueRange.lower)/(mValueRange.upper-mValueRange.lower)*(mValueSize-1)+0.5;
19823 int valueCell = (value-mValueRange.lower)/(mValueRange.upper-mValueRange.lower)*(mValueSize-1)+0.5;
20323 if (keyCell >= 0 && keyCell < mKeySize && valueCell >= 0 && valueCell < mValueSize)
19824 if (keyCell >= 0 && keyCell < mKeySize && valueCell >= 0 && valueCell < mValueSize)
20324 {
19825 {
20325 mData[valueCell*mKeySize + keyCell] = z;
19826 mData[valueCell*mKeySize + keyCell] = z;
20326 if (z < mDataBounds.lower)
19827 if (z < mDataBounds.lower)
20327 mDataBounds.lower = z;
19828 mDataBounds.lower = z;
20328 if (z > mDataBounds.upper)
19829 if (z > mDataBounds.upper)
20329 mDataBounds.upper = z;
19830 mDataBounds.upper = z;
20330 mDataModified = true;
19831 mDataModified = true;
20331 }
19832 }
20332 }
19833 }
20333
19834
@@ -20344,14 +19845,14 void QCPColorMapData::setData(double key
20344 */
19845 */
20345 void QCPColorMapData::setCell(int keyIndex, int valueIndex, double z)
19846 void QCPColorMapData::setCell(int keyIndex, int valueIndex, double z)
20346 {
19847 {
20347 if (keyIndex >= 0 && keyIndex < mKeySize && valueIndex >= 0 && valueIndex < mValueSize)
19848 if (keyIndex >= 0 && keyIndex < mKeySize && valueIndex >= 0 && valueIndex < mValueSize)
20348 {
19849 {
20349 mData[valueIndex*mKeySize + keyIndex] = z;
19850 mData[valueIndex*mKeySize + keyIndex] = z;
20350 if (z < mDataBounds.lower)
19851 if (z < mDataBounds.lower)
20351 mDataBounds.lower = z;
19852 mDataBounds.lower = z;
20352 if (z > mDataBounds.upper)
19853 if (z > mDataBounds.upper)
20353 mDataBounds.upper = z;
19854 mDataBounds.upper = z;
20354 mDataModified = true;
19855 mDataModified = true;
20355 }
19856 }
20356 }
19857 }
20357
19858
@@ -20370,20 +19871,20 void QCPColorMapData::setCell(int keyInd
20370 */
19871 */
20371 void QCPColorMapData::recalculateDataBounds()
19872 void QCPColorMapData::recalculateDataBounds()
20372 {
19873 {
20373 if (mKeySize > 0 && mValueSize > 0)
19874 if (mKeySize > 0 && mValueSize > 0)
20374 {
19875 {
20375 double minHeight = mData[0];
19876 double minHeight = mData[0];
20376 double maxHeight = mData[0];
19877 double maxHeight = mData[0];
20377 const int dataCount = mValueSize*mKeySize;
19878 const int dataCount = mValueSize*mKeySize;
20378 for (int i=0; i<dataCount; ++i)
19879 for (int i=0; i<dataCount; ++i)
20379 {
19880 {
20380 if (mData[i] > maxHeight)
19881 if (mData[i] > maxHeight)
20381 maxHeight = mData[i];
19882 maxHeight = mData[i];
20382 if (mData[i] < minHeight)
19883 if (mData[i] < minHeight)
20383 minHeight = mData[i];
19884 minHeight = mData[i];
20384 }
19885 }
20385 mDataBounds.lower = minHeight;
19886 mDataBounds.lower = minHeight;
20386 mDataBounds.upper = maxHeight;
19887 mDataBounds.upper = maxHeight;
20387 }
19888 }
20388 }
19889 }
20389
19890
@@ -20394,7 +19895,7 void QCPColorMapData::recalculateDataBou
20394 */
19895 */
20395 void QCPColorMapData::clear()
19896 void QCPColorMapData::clear()
20396 {
19897 {
20397 setSize(0, 0);
19898 setSize(0, 0);
20398 }
19899 }
20399
19900
20400 /*!
19901 /*!
@@ -20402,10 +19903,10 void QCPColorMapData::clear()
20402 */
19903 */
20403 void QCPColorMapData::fill(double z)
19904 void QCPColorMapData::fill(double z)
20404 {
19905 {
20405 const int dataCount = mValueSize*mKeySize;
19906 const int dataCount = mValueSize*mKeySize;
20406 for (int i=0; i<dataCount; ++i)
19907 for (int i=0; i<dataCount; ++i)
20407 mData[i] = z;
19908 mData[i] = z;
20408 mDataBounds = QCPRange(z, z);
19909 mDataBounds = QCPRange(z, z);
20409 }
19910 }
20410
19911
20411 /*!
19912 /*!
@@ -20422,10 +19923,10 void QCPColorMapData::fill(double z)
20422 */
19923 */
20423 void QCPColorMapData::coordToCell(double key, double value, int *keyIndex, int *valueIndex) const
19924 void QCPColorMapData::coordToCell(double key, double value, int *keyIndex, int *valueIndex) const
20424 {
19925 {
20425 if (keyIndex)
19926 if (keyIndex)
20426 *keyIndex = (key-mKeyRange.lower)/(mKeyRange.upper-mKeyRange.lower)*(mKeySize-1)+0.5;
19927 *keyIndex = (key-mKeyRange.lower)/(mKeyRange.upper-mKeyRange.lower)*(mKeySize-1)+0.5;
20427 if (valueIndex)
19928 if (valueIndex)
20428 *valueIndex = (value-mValueRange.lower)/(mValueRange.upper-mValueRange.lower)*(mValueSize-1)+0.5;
19929 *valueIndex = (value-mValueRange.lower)/(mValueRange.upper-mValueRange.lower)*(mValueSize-1)+0.5;
20429 }
19930 }
20430
19931
20431 /*!
19932 /*!
@@ -20440,10 +19941,10 void QCPColorMapData::coordToCell(double
20440 */
19941 */
20441 void QCPColorMapData::cellToCoord(int keyIndex, int valueIndex, double *key, double *value) const
19942 void QCPColorMapData::cellToCoord(int keyIndex, int valueIndex, double *key, double *value) const
20442 {
19943 {
20443 if (key)
19944 if (key)
20444 *key = keyIndex/(double)(mKeySize-1)*(mKeyRange.upper-mKeyRange.lower)+mKeyRange.lower;
19945 *key = keyIndex/(double)(mKeySize-1)*(mKeyRange.upper-mKeyRange.lower)+mKeyRange.lower;
20445 if (value)
19946 if (value)
20446 *value = valueIndex/(double)(mValueSize-1)*(mValueRange.upper-mValueRange.lower)+mValueRange.lower;
19947 *value = valueIndex/(double)(mValueSize-1)*(mValueRange.upper-mValueRange.lower)+mValueRange.lower;
20447 }
19948 }
20448
19949
20449
19950
@@ -20567,18 +20068,18 void QCPColorMapData::cellToCoord(int ke
20567 then takes ownership of the color map.
20068 then takes ownership of the color map.
20568 */
20069 */
20569 QCPColorMap::QCPColorMap(QCPAxis *keyAxis, QCPAxis *valueAxis) :
20070 QCPColorMap::QCPColorMap(QCPAxis *keyAxis, QCPAxis *valueAxis) :
20570 QCPAbstractPlottable(keyAxis, valueAxis),
20071 QCPAbstractPlottable(keyAxis, valueAxis),
20571 mDataScaleType(QCPAxis::stLinear),
20072 mDataScaleType(QCPAxis::stLinear),
20572 mMapData(new QCPColorMapData(10, 10, QCPRange(0, 5), QCPRange(0, 5))),
20073 mMapData(new QCPColorMapData(10, 10, QCPRange(0, 5), QCPRange(0, 5))),
20573 mInterpolate(true),
20074 mInterpolate(true),
20574 mTightBoundary(false),
20075 mTightBoundary(false),
20575 mMapImageInvalidated(true)
20076 mMapImageInvalidated(true)
20576 {
20077 {
20577 }
20078 }
20578
20079
20579 QCPColorMap::~QCPColorMap()
20080 QCPColorMap::~QCPColorMap()
20580 {
20081 {
20581 delete mMapData;
20082 delete mMapData;
20582 }
20083 }
20583
20084
20584 /*!
20085 /*!
@@ -20590,20 +20091,20 QCPColorMap::~QCPColorMap()
20590 */
20091 */
20591 void QCPColorMap::setData(QCPColorMapData *data, bool copy)
20092 void QCPColorMap::setData(QCPColorMapData *data, bool copy)
20592 {
20093 {
20593 if (mMapData == data)
20094 if (mMapData == data)
20594 {
20095 {
20595 qDebug() << Q_FUNC_INFO << "The data pointer is already in (and owned by) this plottable" << reinterpret_cast<quintptr>(data);
20096 qDebug() << Q_FUNC_INFO << "The data pointer is already in (and owned by) this plottable" << reinterpret_cast<quintptr>(data);
20596 return;
20097 return;
20597 }
20098 }
20598 if (copy)
20099 if (copy)
20599 {
20100 {
20600 *mMapData = *data;
20101 *mMapData = *data;
20601 } else
20102 } else
20602 {
20103 {
20603 delete mMapData;
20104 delete mMapData;
20604 mMapData = data;
20105 mMapData = data;
20605 }
20106 }
20606 mMapImageInvalidated = true;
20107 mMapImageInvalidated = true;
20607 }
20108 }
20608
20109
20609 /*!
20110 /*!
@@ -20616,15 +20117,15 void QCPColorMap::setData(QCPColorMapDat
20616 */
20117 */
20617 void QCPColorMap::setDataRange(const QCPRange &dataRange)
20118 void QCPColorMap::setDataRange(const QCPRange &dataRange)
20618 {
20119 {
20619 if (!QCPRange::validRange(dataRange)) return;
20120 if (!QCPRange::validRange(dataRange)) return;
20620 if (mDataRange.lower != dataRange.lower || mDataRange.upper != dataRange.upper)
20121 if (mDataRange.lower != dataRange.lower || mDataRange.upper != dataRange.upper)
20621 {
20122 {
20622 if (mDataScaleType == QCPAxis::stLogarithmic)
20123 if (mDataScaleType == QCPAxis::stLogarithmic)
20623 mDataRange = dataRange.sanitizedForLogScale();
20124 mDataRange = dataRange.sanitizedForLogScale();
20624 else
20125 else
20625 mDataRange = dataRange.sanitizedForLinScale();
20126 mDataRange = dataRange.sanitizedForLinScale();
20626 mMapImageInvalidated = true;
20127 mMapImageInvalidated = true;
20627 emit dataRangeChanged(mDataRange);
20128 emit dataRangeChanged(mDataRange);
20628 }
20129 }
20629 }
20130 }
20630
20131
@@ -20635,13 +20136,13 void QCPColorMap::setDataRange(const QCP
20635 */
20136 */
20636 void QCPColorMap::setDataScaleType(QCPAxis::ScaleType scaleType)
20137 void QCPColorMap::setDataScaleType(QCPAxis::ScaleType scaleType)
20637 {
20138 {
20638 if (mDataScaleType != scaleType)
20139 if (mDataScaleType != scaleType)
20639 {
20140 {
20640 mDataScaleType = scaleType;
20141 mDataScaleType = scaleType;
20641 mMapImageInvalidated = true;
20142 mMapImageInvalidated = true;
20642 emit dataScaleTypeChanged(mDataScaleType);
20143 emit dataScaleTypeChanged(mDataScaleType);
20643 if (mDataScaleType == QCPAxis::stLogarithmic)
20144 if (mDataScaleType == QCPAxis::stLogarithmic)
20644 setDataRange(mDataRange.sanitizedForLogScale());
20145 setDataRange(mDataRange.sanitizedForLogScale());
20645 }
20146 }
20646 }
20147 }
20647
20148
@@ -20658,11 +20159,11 void QCPColorMap::setDataScaleType(QCPAx
20658 */
20159 */
20659 void QCPColorMap::setGradient(const QCPColorGradient &gradient)
20160 void QCPColorMap::setGradient(const QCPColorGradient &gradient)
20660 {
20161 {
20661 if (mGradient != gradient)
20162 if (mGradient != gradient)
20662 {
20163 {
20663 mGradient = gradient;
20164 mGradient = gradient;
20664 mMapImageInvalidated = true;
20165 mMapImageInvalidated = true;
20665 emit gradientChanged(mGradient);
20166 emit gradientChanged(mGradient);
20666 }
20167 }
20667 }
20168 }
20668
20169
@@ -20674,7 +20175,7 void QCPColorMap::setGradient(const QCPC
20674 */
20175 */
20675 void QCPColorMap::setInterpolate(bool enabled)
20176 void QCPColorMap::setInterpolate(bool enabled)
20676 {
20177 {
20677 mInterpolate = enabled;
20178 mInterpolate = enabled;
20678 }
20179 }
20679
20180
20680 /*!
20181 /*!
@@ -20690,7 +20191,7 void QCPColorMap::setInterpolate(bool en
20690 */
20191 */
20691 void QCPColorMap::setTightBoundary(bool enabled)
20192 void QCPColorMap::setTightBoundary(bool enabled)
20692 {
20193 {
20693 mTightBoundary = enabled;
20194 mTightBoundary = enabled;
20694 }
20195 }
20695
20196
20696 /*!
20197 /*!
@@ -20709,27 +20210,27 void QCPColorMap::setTightBoundary(bool
20709 */
20210 */
20710 void QCPColorMap::setColorScale(QCPColorScale *colorScale)
20211 void QCPColorMap::setColorScale(QCPColorScale *colorScale)
20711 {
20212 {
20712 if (mColorScale) // unconnect signals from old color scale
20213 if (mColorScale) // unconnect signals from old color scale
20713 {
20214 {
20714 disconnect(this, SIGNAL(dataRangeChanged(QCPRange)), mColorScale.data(), SLOT(setDataRange(QCPRange)));
20215 disconnect(this, SIGNAL(dataRangeChanged(QCPRange)), mColorScale.data(), SLOT(setDataRange(QCPRange)));
20715 disconnect(this, SIGNAL(dataScaleTypeChanged(QCPAxis::ScaleType)), mColorScale.data(), SLOT(setDataScaleType(QCPAxis::ScaleType)));
20216 disconnect(this, SIGNAL(dataScaleTypeChanged(QCPAxis::ScaleType)), mColorScale.data(), SLOT(setDataScaleType(QCPAxis::ScaleType)));
20716 disconnect(this, SIGNAL(gradientChanged(QCPColorGradient)), mColorScale.data(), SLOT(setGradient(QCPColorGradient)));
20217 disconnect(this, SIGNAL(gradientChanged(QCPColorGradient)), mColorScale.data(), SLOT(setGradient(QCPColorGradient)));
20717 disconnect(mColorScale.data(), SIGNAL(dataRangeChanged(QCPRange)), this, SLOT(setDataRange(QCPRange)));
20218 disconnect(mColorScale.data(), SIGNAL(dataRangeChanged(QCPRange)), this, SLOT(setDataRange(QCPRange)));
20718 disconnect(mColorScale.data(), SIGNAL(gradientChanged(QCPColorGradient)), this, SLOT(setGradient(QCPColorGradient)));
20219 disconnect(mColorScale.data(), SIGNAL(gradientChanged(QCPColorGradient)), this, SLOT(setGradient(QCPColorGradient)));
20719 disconnect(mColorScale.data(), SIGNAL(dataScaleTypeChanged(QCPAxis::ScaleType)), this, SLOT(setDataScaleType(QCPAxis::ScaleType)));
20220 disconnect(mColorScale.data(), SIGNAL(dataScaleTypeChanged(QCPAxis::ScaleType)), this, SLOT(setDataScaleType(QCPAxis::ScaleType)));
20720 }
20221 }
20721 mColorScale = colorScale;
20222 mColorScale = colorScale;
20722 if (mColorScale) // connect signals to new color scale
20223 if (mColorScale) // connect signals to new color scale
20723 {
20224 {
20724 setGradient(mColorScale.data()->gradient());
20225 setGradient(mColorScale.data()->gradient());
20725 setDataRange(mColorScale.data()->dataRange());
20226 setDataRange(mColorScale.data()->dataRange());
20726 setDataScaleType(mColorScale.data()->dataScaleType());
20227 setDataScaleType(mColorScale.data()->dataScaleType());
20727 connect(this, SIGNAL(dataRangeChanged(QCPRange)), mColorScale.data(), SLOT(setDataRange(QCPRange)));
20228 connect(this, SIGNAL(dataRangeChanged(QCPRange)), mColorScale.data(), SLOT(setDataRange(QCPRange)));
20728 connect(this, SIGNAL(dataScaleTypeChanged(QCPAxis::ScaleType)), mColorScale.data(), SLOT(setDataScaleType(QCPAxis::ScaleType)));
20229 connect(this, SIGNAL(dataScaleTypeChanged(QCPAxis::ScaleType)), mColorScale.data(), SLOT(setDataScaleType(QCPAxis::ScaleType)));
20729 connect(this, SIGNAL(gradientChanged(QCPColorGradient)), mColorScale.data(), SLOT(setGradient(QCPColorGradient)));
20230 connect(this, SIGNAL(gradientChanged(QCPColorGradient)), mColorScale.data(), SLOT(setGradient(QCPColorGradient)));
20730 connect(mColorScale.data(), SIGNAL(dataRangeChanged(QCPRange)), this, SLOT(setDataRange(QCPRange)));
20231 connect(mColorScale.data(), SIGNAL(dataRangeChanged(QCPRange)), this, SLOT(setDataRange(QCPRange)));
20731 connect(mColorScale.data(), SIGNAL(gradientChanged(QCPColorGradient)), this, SLOT(setGradient(QCPColorGradient)));
20232 connect(mColorScale.data(), SIGNAL(gradientChanged(QCPColorGradient)), this, SLOT(setGradient(QCPColorGradient)));
20732 connect(mColorScale.data(), SIGNAL(dataScaleTypeChanged(QCPAxis::ScaleType)), this, SLOT(setDataScaleType(QCPAxis::ScaleType)));
20233 connect(mColorScale.data(), SIGNAL(dataScaleTypeChanged(QCPAxis::ScaleType)), this, SLOT(setDataScaleType(QCPAxis::ScaleType)));
20733 }
20234 }
20734 }
20235 }
20735
20236
@@ -20755,9 +20256,9 void QCPColorMap::setColorScale(QCPColor
20755 */
20256 */
20756 void QCPColorMap::rescaleDataRange(bool recalculateDataBounds)
20257 void QCPColorMap::rescaleDataRange(bool recalculateDataBounds)
20757 {
20258 {
20758 if (recalculateDataBounds)
20259 if (recalculateDataBounds)
20759 mMapData->recalculateDataBounds();
20260 mMapData->recalculateDataBounds();
20760 setDataRange(mMapData->dataBounds());
20261 setDataRange(mMapData->dataBounds());
20761 }
20262 }
20762
20263
20763 /*!
20264 /*!
@@ -20776,14 +20277,14 void QCPColorMap::rescaleDataRange(bool
20776 */
20277 */
20777 void QCPColorMap::updateLegendIcon(Qt::TransformationMode transformMode, const QSize &thumbSize)
20278 void QCPColorMap::updateLegendIcon(Qt::TransformationMode transformMode, const QSize &thumbSize)
20778 {
20279 {
20779 if (mMapImage.isNull() && !data()->isEmpty())
20280 if (mMapImage.isNull() && !data()->isEmpty())
20780 updateMapImage(); // try to update map image if it's null (happens if no draw has happened yet)
20281 updateMapImage(); // try to update map image if it's null (happens if no draw has happened yet)
20781
20282
20782 if (!mMapImage.isNull()) // might still be null, e.g. if data is empty, so check here again
20283 if (!mMapImage.isNull()) // might still be null, e.g. if data is empty, so check here again
20783 {
20284 {
20784 bool mirrorX = (keyAxis()->orientation() == Qt::Horizontal ? keyAxis() : valueAxis())->rangeReversed();
20285 bool mirrorX = (keyAxis()->orientation() == Qt::Horizontal ? keyAxis() : valueAxis())->rangeReversed();
20785 bool mirrorY = (valueAxis()->orientation() == Qt::Vertical ? valueAxis() : keyAxis())->rangeReversed();
20286 bool mirrorY = (valueAxis()->orientation() == Qt::Vertical ? valueAxis() : keyAxis())->rangeReversed();
20786 mLegendIcon = QPixmap::fromImage(mMapImage.mirrored(mirrorX, mirrorY)).scaled(thumbSize, Qt::KeepAspectRatio, transformMode);
20287 mLegendIcon = QPixmap::fromImage(mMapImage.mirrored(mirrorX, mirrorY)).scaled(thumbSize, Qt::KeepAspectRatio, transformMode);
20787 }
20288 }
20788 }
20289 }
20789
20290
@@ -20793,25 +20294,25 void QCPColorMap::updateLegendIcon(Qt::T
20793 */
20294 */
20794 void QCPColorMap::clearData()
20295 void QCPColorMap::clearData()
20795 {
20296 {
20796 mMapData->clear();
20297 mMapData->clear();
20797 }
20298 }
20798
20299
20799 /* inherits documentation from base class */
20300 /* inherits documentation from base class */
20800 double QCPColorMap::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
20301 double QCPColorMap::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
20801 {
20302 {
20802 Q_UNUSED(details)
20303 Q_UNUSED(details)
20803 if (onlySelectable && !mSelectable)
20304 if (onlySelectable && !mSelectable)
20305 return -1;
20306 if (!mKeyAxis || !mValueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return -1; }
20307
20308 if (mKeyAxis.data()->axisRect()->rect().contains(pos.toPoint()))
20309 {
20310 double posKey, posValue;
20311 pixelsToCoords(pos, posKey, posValue);
20312 if (mMapData->keyRange().contains(posKey) && mMapData->valueRange().contains(posValue))
20313 return mParentPlot->selectionTolerance()*0.99;
20314 }
20804 return -1;
20315 return -1;
20805 if (!mKeyAxis || !mValueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return -1; }
20806
20807 if (mKeyAxis.data()->axisRect()->rect().contains(pos.toPoint()))
20808 {
20809 double posKey, posValue;
20810 pixelsToCoords(pos, posKey, posValue);
20811 if (mMapData->keyRange().contains(posKey) && mMapData->valueRange().contains(posValue))
20812 return mParentPlot->selectionTolerance()*0.99;
20813 }
20814 return -1;
20815 }
20316 }
20816
20317
20817 /*! \internal
20318 /*! \internal
@@ -20825,92 +20326,92 double QCPColorMap::selectTest(const QPo
20825 */
20326 */
20826 void QCPColorMap::updateMapImage()
20327 void QCPColorMap::updateMapImage()
20827 {
20328 {
20828 QCPAxis *keyAxis = mKeyAxis.data();
20329 QCPAxis *keyAxis = mKeyAxis.data();
20829 if (!keyAxis) return;
20330 if (!keyAxis) return;
20830
20331
20831 // resize mMapImage to correct dimensions, according to key/value axes orientation:
20332 // resize mMapImage to correct dimensions, according to key/value axes orientation:
20832 if (keyAxis->orientation() == Qt::Horizontal && (mMapImage.size().width() != mMapData->keySize() || mMapImage.size().height() != mMapData->valueSize()))
20333 if (keyAxis->orientation() == Qt::Horizontal && (mMapImage.size().width() != mMapData->keySize() || mMapImage.size().height() != mMapData->valueSize()))
20833 mMapImage = QImage(QSize(mMapData->keySize(), mMapData->valueSize()), QImage::Format_RGB32);
20334 mMapImage = QImage(QSize(mMapData->keySize(), mMapData->valueSize()), QImage::Format_RGB32);
20834 else if (keyAxis->orientation() == Qt::Vertical && (mMapImage.size().width() != mMapData->valueSize() || mMapImage.size().height() != mMapData->keySize()))
20335 else if (keyAxis->orientation() == Qt::Vertical && (mMapImage.size().width() != mMapData->valueSize() || mMapImage.size().height() != mMapData->keySize()))
20835 mMapImage = QImage(QSize(mMapData->valueSize(), mMapData->keySize()), QImage::Format_RGB32);
20336 mMapImage = QImage(QSize(mMapData->valueSize(), mMapData->keySize()), QImage::Format_RGB32);
20836
20337
20837 const int keySize = mMapData->keySize();
20338 const int keySize = mMapData->keySize();
20838 const int valueSize = mMapData->valueSize();
20339 const int valueSize = mMapData->valueSize();
20839 const double *rawData = mMapData->mData;
20340 const double *rawData = mMapData->mData;
20840
20341
20841 if (keyAxis->orientation() == Qt::Horizontal)
20342 if (keyAxis->orientation() == Qt::Horizontal)
20842 {
20343 {
20843 const int lineCount = valueSize;
20344 const int lineCount = valueSize;
20844 const int rowCount = keySize;
20345 const int rowCount = keySize;
20845 for (int line=0; line<lineCount; ++line)
20346 for (int line=0; line<lineCount; ++line)
20846 {
20347 {
20847 QRgb* pixels = reinterpret_cast<QRgb*>(mMapImage.scanLine(lineCount-1-line)); // invert scanline index because QImage counts scanlines from top, but our vertical index counts from bottom (mathematical coordinate system)
20348 QRgb* pixels = reinterpret_cast<QRgb*>(mMapImage.scanLine(lineCount-1-line)); // invert scanline index because QImage counts scanlines from top, but our vertical index counts from bottom (mathematical coordinate system)
20848 mGradient.colorize(rawData+line*rowCount, mDataRange, pixels, rowCount, 1, mDataScaleType==QCPAxis::stLogarithmic);
20349 mGradient.colorize(rawData+line*rowCount, mDataRange, pixels, rowCount, 1, mDataScaleType==QCPAxis::stLogarithmic);
20849 }
20350 }
20850 } else // keyAxis->orientation() == Qt::Vertical
20351 } else // keyAxis->orientation() == Qt::Vertical
20851 {
20352 {
20852 const int lineCount = keySize;
20353 const int lineCount = keySize;
20853 const int rowCount = valueSize;
20354 const int rowCount = valueSize;
20854 for (int line=0; line<lineCount; ++line)
20355 for (int line=0; line<lineCount; ++line)
20855 {
20356 {
20856 QRgb* pixels = reinterpret_cast<QRgb*>(mMapImage.scanLine(lineCount-1-line)); // invert scanline index because QImage counts scanlines from top, but our vertical index counts from bottom (mathematical coordinate system)
20357 QRgb* pixels = reinterpret_cast<QRgb*>(mMapImage.scanLine(lineCount-1-line)); // invert scanline index because QImage counts scanlines from top, but our vertical index counts from bottom (mathematical coordinate system)
20857 mGradient.colorize(rawData+line, mDataRange, pixels, rowCount, lineCount, mDataScaleType==QCPAxis::stLogarithmic);
20358 mGradient.colorize(rawData+line, mDataRange, pixels, rowCount, lineCount, mDataScaleType==QCPAxis::stLogarithmic);
20858 }
20359 }
20859 }
20360 }
20860
20361
20861 mMapData->mDataModified = false;
20362 mMapData->mDataModified = false;
20862 mMapImageInvalidated = false;
20363 mMapImageInvalidated = false;
20863 }
20364 }
20864
20365
20865 /* inherits documentation from base class */
20366 /* inherits documentation from base class */
20866 void QCPColorMap::draw(QCPPainter *painter)
20367 void QCPColorMap::draw(QCPPainter *painter)
20867 {
20368 {
20868 if (mMapData->isEmpty()) return;
20369 if (mMapData->isEmpty()) return;
20869 if (!mKeyAxis || !mValueAxis) return;
20370 if (!mKeyAxis || !mValueAxis) return;
20870 applyDefaultAntialiasingHint(painter);
20371 applyDefaultAntialiasingHint(painter);
20871
20372
20872 if (mMapData->mDataModified || mMapImageInvalidated)
20373 if (mMapData->mDataModified || mMapImageInvalidated)
20873 updateMapImage();
20374 updateMapImage();
20874
20375
20875 double halfSampleKey = 0;
20376 double halfSampleKey = 0;
20876 double halfSampleValue = 0;
20377 double halfSampleValue = 0;
20877 if (mMapData->keySize() > 1)
20378 if (mMapData->keySize() > 1)
20878 halfSampleKey = 0.5*mMapData->keyRange().size()/(double)(mMapData->keySize()-1);
20379 halfSampleKey = 0.5*mMapData->keyRange().size()/(double)(mMapData->keySize()-1);
20879 if (mMapData->valueSize() > 1)
20380 if (mMapData->valueSize() > 1)
20880 halfSampleValue = 0.5*mMapData->valueRange().size()/(double)(mMapData->valueSize()-1);
20381 halfSampleValue = 0.5*mMapData->valueRange().size()/(double)(mMapData->valueSize()-1);
20881 QRectF imageRect(coordsToPixels(mMapData->keyRange().lower-halfSampleKey, mMapData->valueRange().lower-halfSampleValue),
20382 QRectF imageRect(coordsToPixels(mMapData->keyRange().lower-halfSampleKey, mMapData->valueRange().lower-halfSampleValue),
20882 coordsToPixels(mMapData->keyRange().upper+halfSampleKey, mMapData->valueRange().upper+halfSampleValue));
20383 coordsToPixels(mMapData->keyRange().upper+halfSampleKey, mMapData->valueRange().upper+halfSampleValue));
20883 imageRect = imageRect.normalized();
20384 imageRect = imageRect.normalized();
20884 bool mirrorX = (keyAxis()->orientation() == Qt::Horizontal ? keyAxis() : valueAxis())->rangeReversed();
20385 bool mirrorX = (keyAxis()->orientation() == Qt::Horizontal ? keyAxis() : valueAxis())->rangeReversed();
20885 bool mirrorY = (valueAxis()->orientation() == Qt::Vertical ? valueAxis() : keyAxis())->rangeReversed();
20386 bool mirrorY = (valueAxis()->orientation() == Qt::Vertical ? valueAxis() : keyAxis())->rangeReversed();
20886 bool smoothBackup = painter->renderHints().testFlag(QPainter::SmoothPixmapTransform);
20387 bool smoothBackup = painter->renderHints().testFlag(QPainter::SmoothPixmapTransform);
20887 painter->setRenderHint(QPainter::SmoothPixmapTransform, mInterpolate);
20388 painter->setRenderHint(QPainter::SmoothPixmapTransform, mInterpolate);
20888 QRegion clipBackup;
20389 QRegion clipBackup;
20889 if (mTightBoundary)
20390 if (mTightBoundary)
20890 {
20391 {
20891 clipBackup = painter->clipRegion();
20392 clipBackup = painter->clipRegion();
20892 painter->setClipRect(QRectF(coordsToPixels(mMapData->keyRange().lower, mMapData->valueRange().lower),
20393 painter->setClipRect(QRectF(coordsToPixels(mMapData->keyRange().lower, mMapData->valueRange().lower),
20893 coordsToPixels(mMapData->keyRange().upper, mMapData->valueRange().upper)).normalized(), Qt::IntersectClip);
20394 coordsToPixels(mMapData->keyRange().upper, mMapData->valueRange().upper)).normalized(), Qt::IntersectClip);
20894 }
20395 }
20895 painter->drawImage(imageRect, mMapImage.mirrored(mirrorX, mirrorY));
20396 painter->drawImage(imageRect, mMapImage.mirrored(mirrorX, mirrorY));
20896 if (mTightBoundary)
20397 if (mTightBoundary)
20897 painter->setClipRegion(clipBackup);
20398 painter->setClipRegion(clipBackup);
20898 painter->setRenderHint(QPainter::SmoothPixmapTransform, smoothBackup);
20399 painter->setRenderHint(QPainter::SmoothPixmapTransform, smoothBackup);
20899 }
20400 }
20900
20401
20901 /* inherits documentation from base class */
20402 /* inherits documentation from base class */
20902 void QCPColorMap::drawLegendIcon(QCPPainter *painter, const QRectF &rect) const
20403 void QCPColorMap::drawLegendIcon(QCPPainter *painter, const QRectF &rect) const
20903 {
20404 {
20904 applyDefaultAntialiasingHint(painter);
20405 applyDefaultAntialiasingHint(painter);
20905 // draw map thumbnail:
20406 // draw map thumbnail:
20906 if (!mLegendIcon.isNull())
20407 if (!mLegendIcon.isNull())
20907 {
20408 {
20908 QPixmap scaledIcon = mLegendIcon.scaled(rect.size().toSize(), Qt::KeepAspectRatio, Qt::FastTransformation);
20409 QPixmap scaledIcon = mLegendIcon.scaled(rect.size().toSize(), Qt::KeepAspectRatio, Qt::FastTransformation);
20909 QRectF iconRect = QRectF(0, 0, scaledIcon.width(), scaledIcon.height());
20410 QRectF iconRect = QRectF(0, 0, scaledIcon.width(), scaledIcon.height());
20910 iconRect.moveCenter(rect.center());
20411 iconRect.moveCenter(rect.center());
20911 painter->drawPixmap(iconRect.topLeft(), scaledIcon);
20412 painter->drawPixmap(iconRect.topLeft(), scaledIcon);
20912 }
20413 }
20913 /*
20414 /*
20914 // draw frame:
20415 // draw frame:
20915 painter->setBrush(Qt::NoBrush);
20416 painter->setBrush(Qt::NoBrush);
20916 painter->setPen(Qt::black);
20417 painter->setPen(Qt::black);
@@ -20921,45 +20422,45 void QCPColorMap::drawLegendIcon(QCPPain
20921 /* inherits documentation from base class */
20422 /* inherits documentation from base class */
20922 QCPRange QCPColorMap::getKeyRange(bool &foundRange, SignDomain inSignDomain) const
20423 QCPRange QCPColorMap::getKeyRange(bool &foundRange, SignDomain inSignDomain) const
20923 {
20424 {
20924 foundRange = true;
20425 foundRange = true;
20925 QCPRange result = mMapData->keyRange();
20426 QCPRange result = mMapData->keyRange();
20926 result.normalize();
20427 result.normalize();
20927 if (inSignDomain == QCPAbstractPlottable::sdPositive)
20428 if (inSignDomain == QCPAbstractPlottable::sdPositive)
20928 {
20429 {
20929 if (result.lower <= 0 && result.upper > 0)
20430 if (result.lower <= 0 && result.upper > 0)
20930 result.lower = result.upper*1e-3;
20431 result.lower = result.upper*1e-3;
20931 else if (result.lower <= 0 && result.upper <= 0)
20432 else if (result.lower <= 0 && result.upper <= 0)
20932 foundRange = false;
20433 foundRange = false;
20933 } else if (inSignDomain == QCPAbstractPlottable::sdNegative)
20434 } else if (inSignDomain == QCPAbstractPlottable::sdNegative)
20934 {
20435 {
20935 if (result.upper >= 0 && result.lower < 0)
20436 if (result.upper >= 0 && result.lower < 0)
20936 result.upper = result.lower*1e-3;
20437 result.upper = result.lower*1e-3;
20937 else if (result.upper >= 0 && result.lower >= 0)
20438 else if (result.upper >= 0 && result.lower >= 0)
20938 foundRange = false;
20439 foundRange = false;
20939 }
20440 }
20940 return result;
20441 return result;
20941 }
20442 }
20942
20443
20943 /* inherits documentation from base class */
20444 /* inherits documentation from base class */
20944 QCPRange QCPColorMap::getValueRange(bool &foundRange, SignDomain inSignDomain) const
20445 QCPRange QCPColorMap::getValueRange(bool &foundRange, SignDomain inSignDomain) const
20945 {
20446 {
20946 foundRange = true;
20447 foundRange = true;
20947 QCPRange result = mMapData->valueRange();
20448 QCPRange result = mMapData->valueRange();
20948 result.normalize();
20449 result.normalize();
20949 if (inSignDomain == QCPAbstractPlottable::sdPositive)
20450 if (inSignDomain == QCPAbstractPlottable::sdPositive)
20950 {
20451 {
20951 if (result.lower <= 0 && result.upper > 0)
20452 if (result.lower <= 0 && result.upper > 0)
20952 result.lower = result.upper*1e-3;
20453 result.lower = result.upper*1e-3;
20953 else if (result.lower <= 0 && result.upper <= 0)
20454 else if (result.lower <= 0 && result.upper <= 0)
20954 foundRange = false;
20455 foundRange = false;
20955 } else if (inSignDomain == QCPAbstractPlottable::sdNegative)
20456 } else if (inSignDomain == QCPAbstractPlottable::sdNegative)
20956 {
20457 {
20957 if (result.upper >= 0 && result.lower < 0)
20458 if (result.upper >= 0 && result.lower < 0)
20958 result.upper = result.lower*1e-3;
20459 result.upper = result.lower*1e-3;
20959 else if (result.upper >= 0 && result.lower >= 0)
20460 else if (result.upper >= 0 && result.lower >= 0)
20960 foundRange = false;
20461 foundRange = false;
20961 }
20462 }
20962 return result;
20463 return result;
20963 }
20464 }
20964
20465
20965
20466
@@ -20986,11 +20487,11 QCPRange QCPColorMap::getValueRange(bool
20986 Constructs a data point with key and all values set to zero.
20487 Constructs a data point with key and all values set to zero.
20987 */
20488 */
20988 QCPFinancialData::QCPFinancialData() :
20489 QCPFinancialData::QCPFinancialData() :
20989 key(0),
20490 key(0),
20990 open(0),
20491 open(0),
20991 high(0),
20492 high(0),
20992 low(0),
20493 low(0),
20993 close(0)
20494 close(0)
20994 {
20495 {
20995 }
20496 }
20996
20497
@@ -20998,11 +20499,11 QCPFinancialData::QCPFinancialData() :
20998 Constructs a data point with the specified \a key and OHLC values.
20499 Constructs a data point with the specified \a key and OHLC values.
20999 */
20500 */
21000 QCPFinancialData::QCPFinancialData(double key, double open, double high, double low, double close) :
20501 QCPFinancialData::QCPFinancialData(double key, double open, double high, double low, double close) :
21001 key(key),
20502 key(key),
21002 open(open),
20503 open(open),
21003 high(high),
20504 high(high),
21004 low(low),
20505 low(low),
21005 close(close)
20506 close(close)
21006 {
20507 {
21007 }
20508 }
21008
20509
@@ -21064,25 +20565,25 QCPFinancialData::QCPFinancialData(doubl
21064 then takes ownership of the financial chart.
20565 then takes ownership of the financial chart.
21065 */
20566 */
21066 QCPFinancial::QCPFinancial(QCPAxis *keyAxis, QCPAxis *valueAxis) :
20567 QCPFinancial::QCPFinancial(QCPAxis *keyAxis, QCPAxis *valueAxis) :
21067 QCPAbstractPlottable(keyAxis, valueAxis),
20568 QCPAbstractPlottable(keyAxis, valueAxis),
21068 mData(0),
20569 mData(0),
21069 mChartStyle(csOhlc),
20570 mChartStyle(csOhlc),
21070 mWidth(0.5),
20571 mWidth(0.5),
21071 mTwoColored(false),
20572 mTwoColored(false),
21072 mBrushPositive(QBrush(QColor(210, 210, 255))),
20573 mBrushPositive(QBrush(QColor(210, 210, 255))),
21073 mBrushNegative(QBrush(QColor(255, 210, 210))),
20574 mBrushNegative(QBrush(QColor(255, 210, 210))),
21074 mPenPositive(QPen(QColor(10, 40, 180))),
20575 mPenPositive(QPen(QColor(10, 40, 180))),
21075 mPenNegative(QPen(QColor(180, 40, 10)))
20576 mPenNegative(QPen(QColor(180, 40, 10)))
21076 {
20577 {
21077 mData = new QCPFinancialDataMap;
20578 mData = new QCPFinancialDataMap;
21078
20579
21079 setSelectedPen(QPen(QColor(80, 80, 255), 2.5));
20580 setSelectedPen(QPen(QColor(80, 80, 255), 2.5));
21080 setSelectedBrush(QBrush(QColor(80, 80, 255)));
20581 setSelectedBrush(QBrush(QColor(80, 80, 255)));
21081 }
20582 }
21082
20583
21083 QCPFinancial::~QCPFinancial()
20584 QCPFinancial::~QCPFinancial()
21084 {
20585 {
21085 delete mData;
20586 delete mData;
21086 }
20587 }
21087
20588
21088 /*!
20589 /*!
@@ -21099,18 +20600,18 QCPFinancial::~QCPFinancial()
21099 */
20600 */
21100 void QCPFinancial::setData(QCPFinancialDataMap *data, bool copy)
20601 void QCPFinancial::setData(QCPFinancialDataMap *data, bool copy)
21101 {
20602 {
21102 if (mData == data)
20603 if (mData == data)
21103 {
20604 {
21104 qDebug() << Q_FUNC_INFO << "The data pointer is already in (and owned by) this plottable" << reinterpret_cast<quintptr>(data);
20605 qDebug() << Q_FUNC_INFO << "The data pointer is already in (and owned by) this plottable" << reinterpret_cast<quintptr>(data);
21105 return;
20606 return;
21106 }
20607 }
21107 if (copy)
20608 if (copy)
21108 {
20609 {
21109 *mData = *data;
20610 *mData = *data;
21110 } else
20611 } else
21111 {
20612 {
21112 delete mData;
20613 delete mData;
21113 mData = data;
20614 mData = data;
21114 }
20615 }
21115 }
20616 }
21116
20617
@@ -21123,15 +20624,15 void QCPFinancial::setData(QCPFinancialD
21123 */
20624 */
21124 void QCPFinancial::setData(const QVector<double> &key, const QVector<double> &open, const QVector<double> &high, const QVector<double> &low, const QVector<double> &close)
20625 void QCPFinancial::setData(const QVector<double> &key, const QVector<double> &open, const QVector<double> &high, const QVector<double> &low, const QVector<double> &close)
21125 {
20626 {
21126 mData->clear();
20627 mData->clear();
21127 int n = key.size();
20628 int n = key.size();
21128 n = qMin(n, open.size());
20629 n = qMin(n, open.size());
21129 n = qMin(n, high.size());
20630 n = qMin(n, high.size());
21130 n = qMin(n, low.size());
20631 n = qMin(n, low.size());
21131 n = qMin(n, close.size());
20632 n = qMin(n, close.size());
21132 for (int i=0; i<n; ++i)
20633 for (int i=0; i<n; ++i)
21133 {
20634 {
21134 mData->insertMulti(key[i], QCPFinancialData(key[i], open[i], high[i], low[i], close[i]));
20635 mData->insertMulti(key[i], QCPFinancialData(key[i], open[i], high[i], low[i], close[i]));
21135 }
20636 }
21136 }
20637 }
21137
20638
@@ -21140,7 +20641,7 void QCPFinancial::setData(const QVector
21140 */
20641 */
21141 void QCPFinancial::setChartStyle(QCPFinancial::ChartStyle style)
20642 void QCPFinancial::setChartStyle(QCPFinancial::ChartStyle style)
21142 {
20643 {
21143 mChartStyle = style;
20644 mChartStyle = style;
21144 }
20645 }
21145
20646
21146 /*!
20647 /*!
@@ -21150,7 +20651,7 void QCPFinancial::setChartStyle(QCPFina
21150 */
20651 */
21151 void QCPFinancial::setWidth(double width)
20652 void QCPFinancial::setWidth(double width)
21152 {
20653 {
21153 mWidth = width;
20654 mWidth = width;
21154 }
20655 }
21155
20656
21156 /*!
20657 /*!
@@ -21164,7 +20665,7 void QCPFinancial::setWidth(double width
21164 */
20665 */
21165 void QCPFinancial::setTwoColored(bool twoColored)
20666 void QCPFinancial::setTwoColored(bool twoColored)
21166 {
20667 {
21167 mTwoColored = twoColored;
20668 mTwoColored = twoColored;
21168 }
20669 }
21169
20670
21170 /*!
20671 /*!
@@ -21178,7 +20679,7 void QCPFinancial::setTwoColored(bool tw
21178 */
20679 */
21179 void QCPFinancial::setBrushPositive(const QBrush &brush)
20680 void QCPFinancial::setBrushPositive(const QBrush &brush)
21180 {
20681 {
21181 mBrushPositive = brush;
20682 mBrushPositive = brush;
21182 }
20683 }
21183
20684
21184 /*!
20685 /*!
@@ -21192,7 +20693,7 void QCPFinancial::setBrushPositive(cons
21192 */
20693 */
21193 void QCPFinancial::setBrushNegative(const QBrush &brush)
20694 void QCPFinancial::setBrushNegative(const QBrush &brush)
21194 {
20695 {
21195 mBrushNegative = brush;
20696 mBrushNegative = brush;
21196 }
20697 }
21197
20698
21198 /*!
20699 /*!
@@ -21206,7 +20707,7 void QCPFinancial::setBrushNegative(cons
21206 */
20707 */
21207 void QCPFinancial::setPenPositive(const QPen &pen)
20708 void QCPFinancial::setPenPositive(const QPen &pen)
21208 {
20709 {
21209 mPenPositive = pen;
20710 mPenPositive = pen;
21210 }
20711 }
21211
20712
21212 /*!
20713 /*!
@@ -21220,7 +20721,7 void QCPFinancial::setPenPositive(const
21220 */
20721 */
21221 void QCPFinancial::setPenNegative(const QPen &pen)
20722 void QCPFinancial::setPenNegative(const QPen &pen)
21222 {
20723 {
21223 mPenNegative = pen;
20724 mPenNegative = pen;
21224 }
20725 }
21225
20726
21226 /*!
20727 /*!
@@ -21233,7 +20734,7 void QCPFinancial::setPenNegative(const
21233 */
20734 */
21234 void QCPFinancial::addData(const QCPFinancialDataMap &dataMap)
20735 void QCPFinancial::addData(const QCPFinancialDataMap &dataMap)
21235 {
20736 {
21236 mData->unite(dataMap);
20737 mData->unite(dataMap);
21237 }
20738 }
21238
20739
21239 /*! \overload
20740 /*! \overload
@@ -21247,7 +20748,7 void QCPFinancial::addData(const QCPFina
21247 */
20748 */
21248 void QCPFinancial::addData(const QCPFinancialData &data)
20749 void QCPFinancial::addData(const QCPFinancialData &data)
21249 {
20750 {
21250 mData->insertMulti(data.key, data);
20751 mData->insertMulti(data.key, data);
21251 }
20752 }
21252
20753
21253 /*! \overload
20754 /*! \overload
@@ -21262,7 +20763,7 void QCPFinancial::addData(const QCPFina
21262 */
20763 */
21263 void QCPFinancial::addData(double key, double open, double high, double low, double close)
20764 void QCPFinancial::addData(double key, double open, double high, double low, double close)
21264 {
20765 {
21265 mData->insertMulti(key, QCPFinancialData(key, open, high, low, close));
20766 mData->insertMulti(key, QCPFinancialData(key, open, high, low, close));
21266 }
20767 }
21267
20768
21268 /*! \overload
20769 /*! \overload
@@ -21276,14 +20777,14 void QCPFinancial::addData(double key, d
21276 */
20777 */
21277 void QCPFinancial::addData(const QVector<double> &key, const QVector<double> &open, const QVector<double> &high, const QVector<double> &low, const QVector<double> &close)
20778 void QCPFinancial::addData(const QVector<double> &key, const QVector<double> &open, const QVector<double> &high, const QVector<double> &low, const QVector<double> &close)
21278 {
20779 {
21279 int n = key.size();
20780 int n = key.size();
21280 n = qMin(n, open.size());
20781 n = qMin(n, open.size());
21281 n = qMin(n, high.size());
20782 n = qMin(n, high.size());
21282 n = qMin(n, low.size());
20783 n = qMin(n, low.size());
21283 n = qMin(n, close.size());
20784 n = qMin(n, close.size());
21284 for (int i=0; i<n; ++i)
20785 for (int i=0; i<n; ++i)
21285 {
20786 {
21286 mData->insertMulti(key[i], QCPFinancialData(key[i], open[i], high[i], low[i], close[i]));
20787 mData->insertMulti(key[i], QCPFinancialData(key[i], open[i], high[i], low[i], close[i]));
21287 }
20788 }
21288 }
20789 }
21289
20790
@@ -21294,9 +20795,9 void QCPFinancial::addData(const QVector
21294 */
20795 */
21295 void QCPFinancial::removeDataBefore(double key)
20796 void QCPFinancial::removeDataBefore(double key)
21296 {
20797 {
21297 QCPFinancialDataMap::iterator it = mData->begin();
20798 QCPFinancialDataMap::iterator it = mData->begin();
21298 while (it != mData->end() && it.key() < key)
20799 while (it != mData->end() && it.key() < key)
21299 it = mData->erase(it);
20800 it = mData->erase(it);
21300 }
20801 }
21301
20802
21302 /*!
20803 /*!
@@ -21306,10 +20807,10 void QCPFinancial::removeDataBefore(doub
21306 */
20807 */
21307 void QCPFinancial::removeDataAfter(double key)
20808 void QCPFinancial::removeDataAfter(double key)
21308 {
20809 {
21309 if (mData->isEmpty()) return;
20810 if (mData->isEmpty()) return;
21310 QCPFinancialDataMap::iterator it = mData->upperBound(key);
20811 QCPFinancialDataMap::iterator it = mData->upperBound(key);
21311 while (it != mData->end())
20812 while (it != mData->end())
21312 it = mData->erase(it);
20813 it = mData->erase(it);
21313 }
20814 }
21314
20815
21315 /*!
20816 /*!
@@ -21321,11 +20822,11 void QCPFinancial::removeDataAfter(doubl
21321 */
20822 */
21322 void QCPFinancial::removeData(double fromKey, double toKey)
20823 void QCPFinancial::removeData(double fromKey, double toKey)
21323 {
20824 {
21324 if (fromKey >= toKey || mData->isEmpty()) return;
20825 if (fromKey >= toKey || mData->isEmpty()) return;
21325 QCPFinancialDataMap::iterator it = mData->upperBound(fromKey);
20826 QCPFinancialDataMap::iterator it = mData->upperBound(fromKey);
21326 QCPFinancialDataMap::iterator itEnd = mData->upperBound(toKey);
20827 QCPFinancialDataMap::iterator itEnd = mData->upperBound(toKey);
21327 while (it != itEnd)
20828 while (it != itEnd)
21328 it = mData->erase(it);
20829 it = mData->erase(it);
21329 }
20830 }
21330
20831
21331 /*! \overload
20832 /*! \overload
@@ -21338,7 +20839,7 void QCPFinancial::removeData(double fro
21338 */
20839 */
21339 void QCPFinancial::removeData(double key)
20840 void QCPFinancial::removeData(double key)
21340 {
20841 {
21341 mData->remove(key);
20842 mData->remove(key);
21342 }
20843 }
21343
20844
21344 /*!
20845 /*!
@@ -21348,34 +20849,34 void QCPFinancial::removeData(double key
21348 */
20849 */
21349 void QCPFinancial::clearData()
20850 void QCPFinancial::clearData()
21350 {
20851 {
21351 mData->clear();
20852 mData->clear();
21352 }
20853 }
21353
20854
21354 /* inherits documentation from base class */
20855 /* inherits documentation from base class */
21355 double QCPFinancial::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
20856 double QCPFinancial::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
21356 {
20857 {
21357 Q_UNUSED(details)
20858 Q_UNUSED(details)
21358 if (onlySelectable && !mSelectable)
20859 if (onlySelectable && !mSelectable)
21359 return -1;
21360 if (!mKeyAxis || !mValueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return -1; }
21361
21362 if (mKeyAxis.data()->axisRect()->rect().contains(pos.toPoint()))
21363 {
21364 // get visible data range:
21365 QCPFinancialDataMap::const_iterator lower, upper; // note that upper is the actual upper point, and not 1 step after the upper point
21366 getVisibleDataBounds(lower, upper);
21367 if (lower == mData->constEnd() || upper == mData->constEnd())
21368 return -1;
20860 return -1;
21369 // perform select test according to configured style:
20861 if (!mKeyAxis || !mValueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return -1; }
21370 switch (mChartStyle)
20862
20863 if (mKeyAxis.data()->axisRect()->rect().contains(pos.toPoint()))
20864 {
20865 // get visible data range:
20866 QCPFinancialDataMap::const_iterator lower, upper; // note that upper is the actual upper point, and not 1 step after the upper point
20867 getVisibleDataBounds(lower, upper);
20868 if (lower == mData->constEnd() || upper == mData->constEnd())
20869 return -1;
20870 // perform select test according to configured style:
20871 switch (mChartStyle)
21371 {
20872 {
21372 case QCPFinancial::csOhlc:
20873 case QCPFinancial::csOhlc:
21373 return ohlcSelectTest(pos, lower, upper+1); break;
20874 return ohlcSelectTest(pos, lower, upper+1); break;
21374 case QCPFinancial::csCandlestick:
20875 case QCPFinancial::csCandlestick:
21375 return candlestickSelectTest(pos, lower, upper+1); break;
20876 return candlestickSelectTest(pos, lower, upper+1); break;
21376 }
20877 }
21377 }
20878 }
21378 return -1;
20879 return -1;
21379 }
20880 }
21380
20881
21381 /*!
20882 /*!
@@ -21393,117 +20894,117 double QCPFinancial::selectTest(const QP
21393 */
20894 */
21394 QCPFinancialDataMap QCPFinancial::timeSeriesToOhlc(const QVector<double> &time, const QVector<double> &value, double timeBinSize, double timeBinOffset)
20895 QCPFinancialDataMap QCPFinancial::timeSeriesToOhlc(const QVector<double> &time, const QVector<double> &value, double timeBinSize, double timeBinOffset)
21395 {
20896 {
21396 QCPFinancialDataMap map;
20897 QCPFinancialDataMap map;
21397 int count = qMin(time.size(), value.size());
20898 int count = qMin(time.size(), value.size());
21398 if (count == 0)
20899 if (count == 0)
21399 return QCPFinancialDataMap();
20900 return QCPFinancialDataMap();
21400
20901
21401 QCPFinancialData currentBinData(0, value.first(), value.first(), value.first(), value.first());
20902 QCPFinancialData currentBinData(0, value.first(), value.first(), value.first(), value.first());
21402 int currentBinIndex = qFloor((time.first()-timeBinOffset)/timeBinSize+0.5);
20903 int currentBinIndex = qFloor((time.first()-timeBinOffset)/timeBinSize+0.5);
21403 for (int i=0; i<count; ++i)
20904 for (int i=0; i<count; ++i)
21404 {
20905 {
21405 int index = qFloor((time.at(i)-timeBinOffset)/timeBinSize+0.5);
20906 int index = qFloor((time.at(i)-timeBinOffset)/timeBinSize+0.5);
21406 if (currentBinIndex == index) // data point still in current bin, extend high/low:
20907 if (currentBinIndex == index) // data point still in current bin, extend high/low:
21407 {
20908 {
21408 if (value.at(i) < currentBinData.low) currentBinData.low = value.at(i);
20909 if (value.at(i) < currentBinData.low) currentBinData.low = value.at(i);
21409 if (value.at(i) > currentBinData.high) currentBinData.high = value.at(i);
20910 if (value.at(i) > currentBinData.high) currentBinData.high = value.at(i);
21410 if (i == count-1) // last data point is in current bin, finalize bin:
20911 if (i == count-1) // last data point is in current bin, finalize bin:
21411 {
20912 {
21412 currentBinData.close = value.at(i);
20913 currentBinData.close = value.at(i);
21413 currentBinData.key = timeBinOffset+(index)*timeBinSize;
20914 currentBinData.key = timeBinOffset+(index)*timeBinSize;
21414 map.insert(currentBinData.key, currentBinData);
20915 map.insert(currentBinData.key, currentBinData);
21415 }
20916 }
21416 } else // data point not anymore in current bin, set close of old and open of new bin, and add old to map:
20917 } else // data point not anymore in current bin, set close of old and open of new bin, and add old to map:
21417 {
20918 {
21418 // finalize current bin:
20919 // finalize current bin:
21419 currentBinData.close = value.at(i-1);
20920 currentBinData.close = value.at(i-1);
21420 currentBinData.key = timeBinOffset+(index-1)*timeBinSize;
20921 currentBinData.key = timeBinOffset+(index-1)*timeBinSize;
21421 map.insert(currentBinData.key, currentBinData);
20922 map.insert(currentBinData.key, currentBinData);
21422 // start next bin:
20923 // start next bin:
21423 currentBinIndex = index;
20924 currentBinIndex = index;
21424 currentBinData.open = value.at(i);
20925 currentBinData.open = value.at(i);
21425 currentBinData.high = value.at(i);
20926 currentBinData.high = value.at(i);
21426 currentBinData.low = value.at(i);
20927 currentBinData.low = value.at(i);
21427 }
20928 }
21428 }
20929 }
21429
20930
21430 return map;
20931 return map;
21431 }
20932 }
21432
20933
21433 /* inherits documentation from base class */
20934 /* inherits documentation from base class */
21434 void QCPFinancial::draw(QCPPainter *painter)
20935 void QCPFinancial::draw(QCPPainter *painter)
21435 {
20936 {
21436 // get visible data range:
20937 // get visible data range:
21437 QCPFinancialDataMap::const_iterator lower, upper; // note that upper is the actual upper point, and not 1 step after the upper point
20938 QCPFinancialDataMap::const_iterator lower, upper; // note that upper is the actual upper point, and not 1 step after the upper point
21438 getVisibleDataBounds(lower, upper);
20939 getVisibleDataBounds(lower, upper);
21439 if (lower == mData->constEnd() || upper == mData->constEnd())
20940 if (lower == mData->constEnd() || upper == mData->constEnd())
21440 return;
20941 return;
21441
20942
21442 // draw visible data range according to configured style:
20943 // draw visible data range according to configured style:
21443 switch (mChartStyle)
20944 switch (mChartStyle)
21444 {
20945 {
21445 case QCPFinancial::csOhlc:
20946 case QCPFinancial::csOhlc:
21446 drawOhlcPlot(painter, lower, upper+1); break;
20947 drawOhlcPlot(painter, lower, upper+1); break;
21447 case QCPFinancial::csCandlestick:
20948 case QCPFinancial::csCandlestick:
21448 drawCandlestickPlot(painter, lower, upper+1); break;
20949 drawCandlestickPlot(painter, lower, upper+1); break;
21449 }
20950 }
21450 }
20951 }
21451
20952
21452 /* inherits documentation from base class */
20953 /* inherits documentation from base class */
21453 void QCPFinancial::drawLegendIcon(QCPPainter *painter, const QRectF &rect) const
20954 void QCPFinancial::drawLegendIcon(QCPPainter *painter, const QRectF &rect) const
21454 {
20955 {
21455 painter->setAntialiasing(false); // legend icon especially of csCandlestick looks better without antialiasing
20956 painter->setAntialiasing(false); // legend icon especially of csCandlestick looks better without antialiasing
21456 if (mChartStyle == csOhlc)
20957 if (mChartStyle == csOhlc)
21457 {
20958 {
21458 if (mTwoColored)
20959 if (mTwoColored)
21459 {
20960 {
21460 // draw upper left half icon with positive color:
20961 // draw upper left half icon with positive color:
21461 painter->setBrush(mBrushPositive);
20962 painter->setBrush(mBrushPositive);
21462 painter->setPen(mPenPositive);
20963 painter->setPen(mPenPositive);
21463 painter->setClipRegion(QRegion(QPolygon() << rect.bottomLeft().toPoint() << rect.topRight().toPoint() << rect.topLeft().toPoint()));
20964 painter->setClipRegion(QRegion(QPolygon() << rect.bottomLeft().toPoint() << rect.topRight().toPoint() << rect.topLeft().toPoint()));
21464 painter->drawLine(QLineF(0, rect.height()*0.5, rect.width(), rect.height()*0.5).translated(rect.topLeft()));
20965 painter->drawLine(QLineF(0, rect.height()*0.5, rect.width(), rect.height()*0.5).translated(rect.topLeft()));
21465 painter->drawLine(QLineF(rect.width()*0.2, rect.height()*0.3, rect.width()*0.2, rect.height()*0.5).translated(rect.topLeft()));
20966 painter->drawLine(QLineF(rect.width()*0.2, rect.height()*0.3, rect.width()*0.2, rect.height()*0.5).translated(rect.topLeft()));
21466 painter->drawLine(QLineF(rect.width()*0.8, rect.height()*0.5, rect.width()*0.8, rect.height()*0.7).translated(rect.topLeft()));
20967 painter->drawLine(QLineF(rect.width()*0.8, rect.height()*0.5, rect.width()*0.8, rect.height()*0.7).translated(rect.topLeft()));
21467 // draw bottom right hald icon with negative color:
20968 // draw bottom right hald icon with negative color:
21468 painter->setBrush(mBrushNegative);
20969 painter->setBrush(mBrushNegative);
21469 painter->setPen(mPenNegative);
20970 painter->setPen(mPenNegative);
21470 painter->setClipRegion(QRegion(QPolygon() << rect.bottomLeft().toPoint() << rect.topRight().toPoint() << rect.bottomRight().toPoint()));
20971 painter->setClipRegion(QRegion(QPolygon() << rect.bottomLeft().toPoint() << rect.topRight().toPoint() << rect.bottomRight().toPoint()));
21471 painter->drawLine(QLineF(0, rect.height()*0.5, rect.width(), rect.height()*0.5).translated(rect.topLeft()));
20972 painter->drawLine(QLineF(0, rect.height()*0.5, rect.width(), rect.height()*0.5).translated(rect.topLeft()));
21472 painter->drawLine(QLineF(rect.width()*0.2, rect.height()*0.3, rect.width()*0.2, rect.height()*0.5).translated(rect.topLeft()));
20973 painter->drawLine(QLineF(rect.width()*0.2, rect.height()*0.3, rect.width()*0.2, rect.height()*0.5).translated(rect.topLeft()));
21473 painter->drawLine(QLineF(rect.width()*0.8, rect.height()*0.5, rect.width()*0.8, rect.height()*0.7).translated(rect.topLeft()));
20974 painter->drawLine(QLineF(rect.width()*0.8, rect.height()*0.5, rect.width()*0.8, rect.height()*0.7).translated(rect.topLeft()));
21474 } else
20975 } else
21475 {
20976 {
21476 painter->setBrush(mBrush);
20977 painter->setBrush(mBrush);
21477 painter->setPen(mPen);
20978 painter->setPen(mPen);
21478 painter->drawLine(QLineF(0, rect.height()*0.5, rect.width(), rect.height()*0.5).translated(rect.topLeft()));
20979 painter->drawLine(QLineF(0, rect.height()*0.5, rect.width(), rect.height()*0.5).translated(rect.topLeft()));
21479 painter->drawLine(QLineF(rect.width()*0.2, rect.height()*0.3, rect.width()*0.2, rect.height()*0.5).translated(rect.topLeft()));
20980 painter->drawLine(QLineF(rect.width()*0.2, rect.height()*0.3, rect.width()*0.2, rect.height()*0.5).translated(rect.topLeft()));
21480 painter->drawLine(QLineF(rect.width()*0.8, rect.height()*0.5, rect.width()*0.8, rect.height()*0.7).translated(rect.topLeft()));
20981 painter->drawLine(QLineF(rect.width()*0.8, rect.height()*0.5, rect.width()*0.8, rect.height()*0.7).translated(rect.topLeft()));
21481 }
20982 }
21482 } else if (mChartStyle == csCandlestick)
20983 } else if (mChartStyle == csCandlestick)
21483 {
20984 {
21484 if (mTwoColored)
20985 if (mTwoColored)
21485 {
20986 {
21486 // draw upper left half icon with positive color:
20987 // draw upper left half icon with positive color:
21487 painter->setBrush(mBrushPositive);
20988 painter->setBrush(mBrushPositive);
21488 painter->setPen(mPenPositive);
20989 painter->setPen(mPenPositive);
21489 painter->setClipRegion(QRegion(QPolygon() << rect.bottomLeft().toPoint() << rect.topRight().toPoint() << rect.topLeft().toPoint()));
20990 painter->setClipRegion(QRegion(QPolygon() << rect.bottomLeft().toPoint() << rect.topRight().toPoint() << rect.topLeft().toPoint()));
21490 painter->drawLine(QLineF(0, rect.height()*0.5, rect.width()*0.25, rect.height()*0.5).translated(rect.topLeft()));
20991 painter->drawLine(QLineF(0, rect.height()*0.5, rect.width()*0.25, rect.height()*0.5).translated(rect.topLeft()));
21491 painter->drawLine(QLineF(rect.width()*0.75, rect.height()*0.5, rect.width(), rect.height()*0.5).translated(rect.topLeft()));
20992 painter->drawLine(QLineF(rect.width()*0.75, rect.height()*0.5, rect.width(), rect.height()*0.5).translated(rect.topLeft()));
21492 painter->drawRect(QRectF(rect.width()*0.25, rect.height()*0.25, rect.width()*0.5, rect.height()*0.5).translated(rect.topLeft()));
20993 painter->drawRect(QRectF(rect.width()*0.25, rect.height()*0.25, rect.width()*0.5, rect.height()*0.5).translated(rect.topLeft()));
21493 // draw bottom right hald icon with negative color:
20994 // draw bottom right hald icon with negative color:
21494 painter->setBrush(mBrushNegative);
20995 painter->setBrush(mBrushNegative);
21495 painter->setPen(mPenNegative);
20996 painter->setPen(mPenNegative);
21496 painter->setClipRegion(QRegion(QPolygon() << rect.bottomLeft().toPoint() << rect.topRight().toPoint() << rect.bottomRight().toPoint()));
20997 painter->setClipRegion(QRegion(QPolygon() << rect.bottomLeft().toPoint() << rect.topRight().toPoint() << rect.bottomRight().toPoint()));
21497 painter->drawLine(QLineF(0, rect.height()*0.5, rect.width()*0.25, rect.height()*0.5).translated(rect.topLeft()));
20998 painter->drawLine(QLineF(0, rect.height()*0.5, rect.width()*0.25, rect.height()*0.5).translated(rect.topLeft()));
21498 painter->drawLine(QLineF(rect.width()*0.75, rect.height()*0.5, rect.width(), rect.height()*0.5).translated(rect.topLeft()));
20999 painter->drawLine(QLineF(rect.width()*0.75, rect.height()*0.5, rect.width(), rect.height()*0.5).translated(rect.topLeft()));
21499 painter->drawRect(QRectF(rect.width()*0.25, rect.height()*0.25, rect.width()*0.5, rect.height()*0.5).translated(rect.topLeft()));
21000 painter->drawRect(QRectF(rect.width()*0.25, rect.height()*0.25, rect.width()*0.5, rect.height()*0.5).translated(rect.topLeft()));
21500 } else
21001 } else
21501 {
21002 {
21502 painter->setBrush(mBrush);
21003 painter->setBrush(mBrush);
21503 painter->setPen(mPen);
21004 painter->setPen(mPen);
21504 painter->drawLine(QLineF(0, rect.height()*0.5, rect.width()*0.25, rect.height()*0.5).translated(rect.topLeft()));
21005 painter->drawLine(QLineF(0, rect.height()*0.5, rect.width()*0.25, rect.height()*0.5).translated(rect.topLeft()));
21505 painter->drawLine(QLineF(rect.width()*0.75, rect.height()*0.5, rect.width(), rect.height()*0.5).translated(rect.topLeft()));
21006 painter->drawLine(QLineF(rect.width()*0.75, rect.height()*0.5, rect.width(), rect.height()*0.5).translated(rect.topLeft()));
21506 painter->drawRect(QRectF(rect.width()*0.25, rect.height()*0.25, rect.width()*0.5, rect.height()*0.5).translated(rect.topLeft()));
21007 painter->drawRect(QRectF(rect.width()*0.25, rect.height()*0.25, rect.width()*0.5, rect.height()*0.5).translated(rect.topLeft()));
21507 }
21008 }
21508 }
21009 }
21509 }
21010 }
@@ -21511,82 +21012,82 void QCPFinancial::drawLegendIcon(QCPPai
21511 /* inherits documentation from base class */
21012 /* inherits documentation from base class */
21512 QCPRange QCPFinancial::getKeyRange(bool &foundRange, QCPAbstractPlottable::SignDomain inSignDomain) const
21013 QCPRange QCPFinancial::getKeyRange(bool &foundRange, QCPAbstractPlottable::SignDomain inSignDomain) const
21513 {
21014 {
21514 QCPRange range;
21015 QCPRange range;
21515 bool haveLower = false;
21016 bool haveLower = false;
21516 bool haveUpper = false;
21017 bool haveUpper = false;
21517
21018
21518 double current;
21019 double current;
21519 QCPFinancialDataMap::const_iterator it = mData->constBegin();
21020 QCPFinancialDataMap::const_iterator it = mData->constBegin();
21520 while (it != mData->constEnd())
21021 while (it != mData->constEnd())
21521 {
21022 {
21522 current = it.value().key;
21023 current = it.value().key;
21523 if (inSignDomain == sdBoth || (inSignDomain == sdNegative && current < 0) || (inSignDomain == sdPositive && current > 0))
21024 if (inSignDomain == sdBoth || (inSignDomain == sdNegative && current < 0) || (inSignDomain == sdPositive && current > 0))
21524 {
21025 {
21525 if (current < range.lower || !haveLower)
21026 if (current < range.lower || !haveLower)
21526 {
21027 {
21527 range.lower = current;
21028 range.lower = current;
21528 haveLower = true;
21029 haveLower = true;
21529 }
21030 }
21530 if (current > range.upper || !haveUpper)
21031 if (current > range.upper || !haveUpper)
21531 {
21032 {
21532 range.upper = current;
21033 range.upper = current;
21533 haveUpper = true;
21034 haveUpper = true;
21534 }
21035 }
21535 }
21036 }
21536 ++it;
21037 ++it;
21537 }
21038 }
21538 // determine exact range by including width of bars/flags:
21039 // determine exact range by including width of bars/flags:
21539 if (haveLower && mKeyAxis)
21040 if (haveLower && mKeyAxis)
21540 range.lower = range.lower-mWidth*0.5;
21041 range.lower = range.lower-mWidth*0.5;
21541 if (haveUpper && mKeyAxis)
21042 if (haveUpper && mKeyAxis)
21542 range.upper = range.upper+mWidth*0.5;
21043 range.upper = range.upper+mWidth*0.5;
21543 foundRange = haveLower && haveUpper;
21044 foundRange = haveLower && haveUpper;
21544 return range;
21045 return range;
21545 }
21046 }
21546
21047
21547 /* inherits documentation from base class */
21048 /* inherits documentation from base class */
21548 QCPRange QCPFinancial::getValueRange(bool &foundRange, QCPAbstractPlottable::SignDomain inSignDomain) const
21049 QCPRange QCPFinancial::getValueRange(bool &foundRange, QCPAbstractPlottable::SignDomain inSignDomain) const
21549 {
21050 {
21550 QCPRange range;
21051 QCPRange range;
21551 bool haveLower = false;
21052 bool haveLower = false;
21552 bool haveUpper = false;
21053 bool haveUpper = false;
21553
21054
21554 QCPFinancialDataMap::const_iterator it = mData->constBegin();
21055 QCPFinancialDataMap::const_iterator it = mData->constBegin();
21555 while (it != mData->constEnd())
21056 while (it != mData->constEnd())
21556 {
21057 {
21557 // high:
21058 // high:
21558 if (inSignDomain == sdBoth || (inSignDomain == sdNegative && it.value().high < 0) || (inSignDomain == sdPositive && it.value().high > 0))
21059 if (inSignDomain == sdBoth || (inSignDomain == sdNegative && it.value().high < 0) || (inSignDomain == sdPositive && it.value().high > 0))
21559 {
21060 {
21560 if (it.value().high < range.lower || !haveLower)
21061 if (it.value().high < range.lower || !haveLower)
21561 {
21062 {
21562 range.lower = it.value().high;
21063 range.lower = it.value().high;
21563 haveLower = true;
21064 haveLower = true;
21564 }
21065 }
21565 if (it.value().high > range.upper || !haveUpper)
21066 if (it.value().high > range.upper || !haveUpper)
21566 {
21067 {
21567 range.upper = it.value().high;
21068 range.upper = it.value().high;
21568 haveUpper = true;
21069 haveUpper = true;
21569 }
21070 }
21570 }
21071 }
21571 // low:
21072 // low:
21572 if (inSignDomain == sdBoth || (inSignDomain == sdNegative && it.value().low < 0) || (inSignDomain == sdPositive && it.value().low > 0))
21073 if (inSignDomain == sdBoth || (inSignDomain == sdNegative && it.value().low < 0) || (inSignDomain == sdPositive && it.value().low > 0))
21573 {
21074 {
21574 if (it.value().low < range.lower || !haveLower)
21075 if (it.value().low < range.lower || !haveLower)
21575 {
21076 {
21576 range.lower = it.value().low;
21077 range.lower = it.value().low;
21577 haveLower = true;
21078 haveLower = true;
21578 }
21079 }
21579 if (it.value().low > range.upper || !haveUpper)
21080 if (it.value().low > range.upper || !haveUpper)
21580 {
21081 {
21581 range.upper = it.value().low;
21082 range.upper = it.value().low;
21582 haveUpper = true;
21083 haveUpper = true;
21583 }
21084 }
21584 }
21085 }
21585 ++it;
21086 ++it;
21586 }
21087 }
21587
21088
21588 foundRange = haveLower && haveUpper;
21089 foundRange = haveLower && haveUpper;
21589 return range;
21090 return range;
21590 }
21091 }
21591
21092
21592 /*! \internal
21093 /*! \internal
@@ -21597,55 +21098,55 QCPRange QCPFinancial::getValueRange(boo
21597 */
21098 */
21598 void QCPFinancial::drawOhlcPlot(QCPPainter *painter, const QCPFinancialDataMap::const_iterator &begin, const QCPFinancialDataMap::const_iterator &end)
21099 void QCPFinancial::drawOhlcPlot(QCPPainter *painter, const QCPFinancialDataMap::const_iterator &begin, const QCPFinancialDataMap::const_iterator &end)
21599 {
21100 {
21600 QCPAxis *keyAxis = mKeyAxis.data();
21101 QCPAxis *keyAxis = mKeyAxis.data();
21601 QCPAxis *valueAxis = mValueAxis.data();
21102 QCPAxis *valueAxis = mValueAxis.data();
21602 if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
21103 if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
21603
21104
21604 QPen linePen;
21105 QPen linePen;
21605
21106
21606 if (keyAxis->orientation() == Qt::Horizontal)
21107 if (keyAxis->orientation() == Qt::Horizontal)
21607 {
21108 {
21608 for (QCPFinancialDataMap::const_iterator it = begin; it != end; ++it)
21109 for (QCPFinancialDataMap::const_iterator it = begin; it != end; ++it)
21609 {
21110 {
21610 if (mSelected)
21111 if (mSelected)
21611 linePen = mSelectedPen;
21112 linePen = mSelectedPen;
21612 else if (mTwoColored)
21113 else if (mTwoColored)
21613 linePen = it.value().close >= it.value().open ? mPenPositive : mPenNegative;
21114 linePen = it.value().close >= it.value().open ? mPenPositive : mPenNegative;
21614 else
21115 else
21615 linePen = mPen;
21116 linePen = mPen;
21616 painter->setPen(linePen);
21117 painter->setPen(linePen);
21617 double keyPixel = keyAxis->coordToPixel(it.value().key);
21118 double keyPixel = keyAxis->coordToPixel(it.value().key);
21618 double openPixel = valueAxis->coordToPixel(it.value().open);
21119 double openPixel = valueAxis->coordToPixel(it.value().open);
21619 double closePixel = valueAxis->coordToPixel(it.value().close);
21120 double closePixel = valueAxis->coordToPixel(it.value().close);
21620 // draw backbone:
21121 // draw backbone:
21621 painter->drawLine(QPointF(keyPixel, valueAxis->coordToPixel(it.value().high)), QPointF(keyPixel, valueAxis->coordToPixel(it.value().low)));
21122 painter->drawLine(QPointF(keyPixel, valueAxis->coordToPixel(it.value().high)), QPointF(keyPixel, valueAxis->coordToPixel(it.value().low)));
21622 // draw open:
21123 // draw open:
21623 double keyWidthPixels = keyPixel-keyAxis->coordToPixel(it.value().key-mWidth*0.5); // sign of this makes sure open/close are on correct sides
21124 double keyWidthPixels = keyPixel-keyAxis->coordToPixel(it.value().key-mWidth*0.5); // sign of this makes sure open/close are on correct sides
21624 painter->drawLine(QPointF(keyPixel-keyWidthPixels, openPixel), QPointF(keyPixel, openPixel));
21125 painter->drawLine(QPointF(keyPixel-keyWidthPixels, openPixel), QPointF(keyPixel, openPixel));
21625 // draw close:
21126 // draw close:
21626 painter->drawLine(QPointF(keyPixel, closePixel), QPointF(keyPixel+keyWidthPixels, closePixel));
21127 painter->drawLine(QPointF(keyPixel, closePixel), QPointF(keyPixel+keyWidthPixels, closePixel));
21627 }
21128 }
21628 } else
21129 } else
21629 {
21130 {
21630 for (QCPFinancialDataMap::const_iterator it = begin; it != end; ++it)
21131 for (QCPFinancialDataMap::const_iterator it = begin; it != end; ++it)
21631 {
21132 {
21632 if (mSelected)
21133 if (mSelected)
21633 linePen = mSelectedPen;
21134 linePen = mSelectedPen;
21634 else if (mTwoColored)
21135 else if (mTwoColored)
21635 linePen = it.value().close >= it.value().open ? mPenPositive : mPenNegative;
21136 linePen = it.value().close >= it.value().open ? mPenPositive : mPenNegative;
21636 else
21137 else
21637 linePen = mPen;
21138 linePen = mPen;
21638 painter->setPen(linePen);
21139 painter->setPen(linePen);
21639 double keyPixel = keyAxis->coordToPixel(it.value().key);
21140 double keyPixel = keyAxis->coordToPixel(it.value().key);
21640 double openPixel = valueAxis->coordToPixel(it.value().open);
21141 double openPixel = valueAxis->coordToPixel(it.value().open);
21641 double closePixel = valueAxis->coordToPixel(it.value().close);
21142 double closePixel = valueAxis->coordToPixel(it.value().close);
21642 // draw backbone:
21143 // draw backbone:
21643 painter->drawLine(QPointF(valueAxis->coordToPixel(it.value().high), keyPixel), QPointF(valueAxis->coordToPixel(it.value().low), keyPixel));
21144 painter->drawLine(QPointF(valueAxis->coordToPixel(it.value().high), keyPixel), QPointF(valueAxis->coordToPixel(it.value().low), keyPixel));
21644 // draw open:
21145 // draw open:
21645 double keyWidthPixels = keyPixel-keyAxis->coordToPixel(it.value().key-mWidth*0.5); // sign of this makes sure open/close are on correct sides
21146 double keyWidthPixels = keyPixel-keyAxis->coordToPixel(it.value().key-mWidth*0.5); // sign of this makes sure open/close are on correct sides
21646 painter->drawLine(QPointF(openPixel, keyPixel-keyWidthPixels), QPointF(openPixel, keyPixel));
21147 painter->drawLine(QPointF(openPixel, keyPixel-keyWidthPixels), QPointF(openPixel, keyPixel));
21647 // draw close:
21148 // draw close:
21648 painter->drawLine(QPointF(closePixel, keyPixel), QPointF(closePixel, keyPixel+keyWidthPixels));
21149 painter->drawLine(QPointF(closePixel, keyPixel), QPointF(closePixel, keyPixel+keyWidthPixels));
21649 }
21150 }
21650 }
21151 }
21651 }
21152 }
@@ -21658,86 +21159,86 void QCPFinancial::drawOhlcPlot(QCPPaint
21658 */
21159 */
21659 void QCPFinancial::drawCandlestickPlot(QCPPainter *painter, const QCPFinancialDataMap::const_iterator &begin, const QCPFinancialDataMap::const_iterator &end)
21160 void QCPFinancial::drawCandlestickPlot(QCPPainter *painter, const QCPFinancialDataMap::const_iterator &begin, const QCPFinancialDataMap::const_iterator &end)
21660 {
21161 {
21661 QCPAxis *keyAxis = mKeyAxis.data();
21162 QCPAxis *keyAxis = mKeyAxis.data();
21662 QCPAxis *valueAxis = mValueAxis.data();
21163 QCPAxis *valueAxis = mValueAxis.data();
21663 if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
21164 if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
21664
21165
21665 QPen linePen;
21166 QPen linePen;
21666 QBrush boxBrush;
21167 QBrush boxBrush;
21667
21168
21668 if (keyAxis->orientation() == Qt::Horizontal)
21169 if (keyAxis->orientation() == Qt::Horizontal)
21669 {
21170 {
21670 for (QCPFinancialDataMap::const_iterator it = begin; it != end; ++it)
21171 for (QCPFinancialDataMap::const_iterator it = begin; it != end; ++it)
21671 {
21172 {
21672 if (mSelected)
21173 if (mSelected)
21673 {
21174 {
21674 linePen = mSelectedPen;
21175 linePen = mSelectedPen;
21675 boxBrush = mSelectedBrush;
21176 boxBrush = mSelectedBrush;
21676 } else if (mTwoColored)
21177 } else if (mTwoColored)
21677 {
21178 {
21678 if (it.value().close >= it.value().open)
21179 if (it.value().close >= it.value().open)
21679 {
21180 {
21680 linePen = mPenPositive;
21181 linePen = mPenPositive;
21681 boxBrush = mBrushPositive;
21182 boxBrush = mBrushPositive;
21682 } else
21183 } else
21683 {
21184 {
21684 linePen = mPenNegative;
21185 linePen = mPenNegative;
21685 boxBrush = mBrushNegative;
21186 boxBrush = mBrushNegative;
21686 }
21187 }
21687 } else
21188 } else
21688 {
21189 {
21689 linePen = mPen;
21190 linePen = mPen;
21690 boxBrush = mBrush;
21191 boxBrush = mBrush;
21691 }
21192 }
21692 painter->setPen(linePen);
21193 painter->setPen(linePen);
21693 painter->setBrush(boxBrush);
21194 painter->setBrush(boxBrush);
21694 double keyPixel = keyAxis->coordToPixel(it.value().key);
21195 double keyPixel = keyAxis->coordToPixel(it.value().key);
21695 double openPixel = valueAxis->coordToPixel(it.value().open);
21196 double openPixel = valueAxis->coordToPixel(it.value().open);
21696 double closePixel = valueAxis->coordToPixel(it.value().close);
21197 double closePixel = valueAxis->coordToPixel(it.value().close);
21697 // draw high:
21198 // draw high:
21698 painter->drawLine(QPointF(keyPixel, valueAxis->coordToPixel(it.value().high)), QPointF(keyPixel, valueAxis->coordToPixel(qMax(it.value().open, it.value().close))));
21199 painter->drawLine(QPointF(keyPixel, valueAxis->coordToPixel(it.value().high)), QPointF(keyPixel, valueAxis->coordToPixel(qMax(it.value().open, it.value().close))));
21699 // draw low:
21200 // draw low:
21700 painter->drawLine(QPointF(keyPixel, valueAxis->coordToPixel(it.value().low)), QPointF(keyPixel, valueAxis->coordToPixel(qMin(it.value().open, it.value().close))));
21201 painter->drawLine(QPointF(keyPixel, valueAxis->coordToPixel(it.value().low)), QPointF(keyPixel, valueAxis->coordToPixel(qMin(it.value().open, it.value().close))));
21701 // draw open-close box:
21202 // draw open-close box:
21702 double keyWidthPixels = keyPixel-keyAxis->coordToPixel(it.value().key-mWidth*0.5);
21203 double keyWidthPixels = keyPixel-keyAxis->coordToPixel(it.value().key-mWidth*0.5);
21703 painter->drawRect(QRectF(QPointF(keyPixel-keyWidthPixels, closePixel), QPointF(keyPixel+keyWidthPixels, openPixel)));
21204 painter->drawRect(QRectF(QPointF(keyPixel-keyWidthPixels, closePixel), QPointF(keyPixel+keyWidthPixels, openPixel)));
21704 }
21205 }
21705 } else // keyAxis->orientation() == Qt::Vertical
21206 } else // keyAxis->orientation() == Qt::Vertical
21706 {
21207 {
21707 for (QCPFinancialDataMap::const_iterator it = begin; it != end; ++it)
21208 for (QCPFinancialDataMap::const_iterator it = begin; it != end; ++it)
21708 {
21209 {
21709 if (mSelected)
21210 if (mSelected)
21710 {
21211 {
21711 linePen = mSelectedPen;
21212 linePen = mSelectedPen;
21712 boxBrush = mSelectedBrush;
21213 boxBrush = mSelectedBrush;
21713 } else if (mTwoColored)
21214 } else if (mTwoColored)
21714 {
21215 {
21715 if (it.value().close >= it.value().open)
21216 if (it.value().close >= it.value().open)
21716 {
21217 {
21717 linePen = mPenPositive;
21218 linePen = mPenPositive;
21718 boxBrush = mBrushPositive;
21219 boxBrush = mBrushPositive;
21719 } else
21220 } else
21720 {
21221 {
21721 linePen = mPenNegative;
21222 linePen = mPenNegative;
21722 boxBrush = mBrushNegative;
21223 boxBrush = mBrushNegative;
21723 }
21224 }
21724 } else
21225 } else
21725 {
21226 {
21726 linePen = mPen;
21227 linePen = mPen;
21727 boxBrush = mBrush;
21228 boxBrush = mBrush;
21728 }
21229 }
21729 painter->setPen(linePen);
21230 painter->setPen(linePen);
21730 painter->setBrush(boxBrush);
21231 painter->setBrush(boxBrush);
21731 double keyPixel = keyAxis->coordToPixel(it.value().key);
21232 double keyPixel = keyAxis->coordToPixel(it.value().key);
21732 double openPixel = valueAxis->coordToPixel(it.value().open);
21233 double openPixel = valueAxis->coordToPixel(it.value().open);
21733 double closePixel = valueAxis->coordToPixel(it.value().close);
21234 double closePixel = valueAxis->coordToPixel(it.value().close);
21734 // draw high:
21235 // draw high:
21735 painter->drawLine(QPointF(valueAxis->coordToPixel(it.value().high), keyPixel), QPointF(valueAxis->coordToPixel(qMax(it.value().open, it.value().close)), keyPixel));
21236 painter->drawLine(QPointF(valueAxis->coordToPixel(it.value().high), keyPixel), QPointF(valueAxis->coordToPixel(qMax(it.value().open, it.value().close)), keyPixel));
21736 // draw low:
21237 // draw low:
21737 painter->drawLine(QPointF(valueAxis->coordToPixel(it.value().low), keyPixel), QPointF(valueAxis->coordToPixel(qMin(it.value().open, it.value().close)), keyPixel));
21238 painter->drawLine(QPointF(valueAxis->coordToPixel(it.value().low), keyPixel), QPointF(valueAxis->coordToPixel(qMin(it.value().open, it.value().close)), keyPixel));
21738 // draw open-close box:
21239 // draw open-close box:
21739 double keyWidthPixels = keyPixel-keyAxis->coordToPixel(it.value().key-mWidth*0.5);
21240 double keyWidthPixels = keyPixel-keyAxis->coordToPixel(it.value().key-mWidth*0.5);
21740 painter->drawRect(QRectF(QPointF(closePixel, keyPixel-keyWidthPixels), QPointF(openPixel, keyPixel+keyWidthPixels)));
21241 painter->drawRect(QRectF(QPointF(closePixel, keyPixel-keyWidthPixels), QPointF(openPixel, keyPixel+keyWidthPixels)));
21741 }
21242 }
21742 }
21243 }
21743 }
21244 }
@@ -21749,34 +21250,34 void QCPFinancial::drawCandlestickPlot(Q
21749 */
21250 */
21750 double QCPFinancial::ohlcSelectTest(const QPointF &pos, const QCPFinancialDataMap::const_iterator &begin, const QCPFinancialDataMap::const_iterator &end) const
21251 double QCPFinancial::ohlcSelectTest(const QPointF &pos, const QCPFinancialDataMap::const_iterator &begin, const QCPFinancialDataMap::const_iterator &end) const
21751 {
21252 {
21752 QCPAxis *keyAxis = mKeyAxis.data();
21253 QCPAxis *keyAxis = mKeyAxis.data();
21753 QCPAxis *valueAxis = mValueAxis.data();
21254 QCPAxis *valueAxis = mValueAxis.data();
21754 if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return -1; }
21255 if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return -1; }
21755
21256
21756 double minDistSqr = std::numeric_limits<double>::max();
21257 double minDistSqr = std::numeric_limits<double>::max();
21757 QCPFinancialDataMap::const_iterator it;
21258 QCPFinancialDataMap::const_iterator it;
21758 if (keyAxis->orientation() == Qt::Horizontal)
21259 if (keyAxis->orientation() == Qt::Horizontal)
21759 {
21260 {
21760 for (it = begin; it != end; ++it)
21261 for (it = begin; it != end; ++it)
21761 {
21262 {
21762 double keyPixel = keyAxis->coordToPixel(it.value().key);
21263 double keyPixel = keyAxis->coordToPixel(it.value().key);
21763 // calculate distance to backbone:
21264 // calculate distance to backbone:
21764 double currentDistSqr = distSqrToLine(QPointF(keyPixel, valueAxis->coordToPixel(it.value().high)), QPointF(keyPixel, valueAxis->coordToPixel(it.value().low)), pos);
21265 double currentDistSqr = distSqrToLine(QPointF(keyPixel, valueAxis->coordToPixel(it.value().high)), QPointF(keyPixel, valueAxis->coordToPixel(it.value().low)), pos);
21765 if (currentDistSqr < minDistSqr)
21266 if (currentDistSqr < minDistSqr)
21766 minDistSqr = currentDistSqr;
21267 minDistSqr = currentDistSqr;
21767 }
21268 }
21768 } else // keyAxis->orientation() == Qt::Vertical
21269 } else // keyAxis->orientation() == Qt::Vertical
21769 {
21270 {
21770 for (it = begin; it != end; ++it)
21271 for (it = begin; it != end; ++it)
21771 {
21272 {
21772 double keyPixel = keyAxis->coordToPixel(it.value().key);
21273 double keyPixel = keyAxis->coordToPixel(it.value().key);
21773 // calculate distance to backbone:
21274 // calculate distance to backbone:
21774 double currentDistSqr = distSqrToLine(QPointF(valueAxis->coordToPixel(it.value().high), keyPixel), QPointF(valueAxis->coordToPixel(it.value().low), keyPixel), pos);
21275 double currentDistSqr = distSqrToLine(QPointF(valueAxis->coordToPixel(it.value().high), keyPixel), QPointF(valueAxis->coordToPixel(it.value().low), keyPixel), pos);
21775 if (currentDistSqr < minDistSqr)
21276 if (currentDistSqr < minDistSqr)
21776 minDistSqr = currentDistSqr;
21277 minDistSqr = currentDistSqr;
21777 }
21278 }
21778 }
21279 }
21779 return qSqrt(minDistSqr);
21280 return qSqrt(minDistSqr);
21780 }
21281 }
21781
21282
21782 /*! \internal
21283 /*! \internal
@@ -21787,62 +21288,62 double QCPFinancial::ohlcSelectTest(cons
21787 */
21288 */
21788 double QCPFinancial::candlestickSelectTest(const QPointF &pos, const QCPFinancialDataMap::const_iterator &begin, const QCPFinancialDataMap::const_iterator &end) const
21289 double QCPFinancial::candlestickSelectTest(const QPointF &pos, const QCPFinancialDataMap::const_iterator &begin, const QCPFinancialDataMap::const_iterator &end) const
21789 {
21290 {
21790 QCPAxis *keyAxis = mKeyAxis.data();
21291 QCPAxis *keyAxis = mKeyAxis.data();
21791 QCPAxis *valueAxis = mValueAxis.data();
21292 QCPAxis *valueAxis = mValueAxis.data();
21792 if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return -1; }
21293 if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return -1; }
21793
21294
21794 double minDistSqr = std::numeric_limits<double>::max();
21295 double minDistSqr = std::numeric_limits<double>::max();
21795 QCPFinancialDataMap::const_iterator it;
21296 QCPFinancialDataMap::const_iterator it;
21796 if (keyAxis->orientation() == Qt::Horizontal)
21297 if (keyAxis->orientation() == Qt::Horizontal)
21797 {
21298 {
21798 for (it = begin; it != end; ++it)
21299 for (it = begin; it != end; ++it)
21799 {
21300 {
21800 double currentDistSqr;
21301 double currentDistSqr;
21801 // determine whether pos is in open-close-box:
21302 // determine whether pos is in open-close-box:
21802 QCPRange boxKeyRange(it.value().key-mWidth*0.5, it.value().key+mWidth*0.5);
21303 QCPRange boxKeyRange(it.value().key-mWidth*0.5, it.value().key+mWidth*0.5);
21803 QCPRange boxValueRange(it.value().close, it.value().open);
21304 QCPRange boxValueRange(it.value().close, it.value().open);
21804 double posKey, posValue;
21305 double posKey, posValue;
21805 pixelsToCoords(pos, posKey, posValue);
21306 pixelsToCoords(pos, posKey, posValue);
21806 if (boxKeyRange.contains(posKey) && boxValueRange.contains(posValue)) // is in open-close-box
21307 if (boxKeyRange.contains(posKey) && boxValueRange.contains(posValue)) // is in open-close-box
21807 {
21308 {
21808 currentDistSqr = mParentPlot->selectionTolerance()*0.99 * mParentPlot->selectionTolerance()*0.99;
21309 currentDistSqr = mParentPlot->selectionTolerance()*0.99 * mParentPlot->selectionTolerance()*0.99;
21809 } else
21310 } else
21810 {
21311 {
21811 // calculate distance to high/low lines:
21312 // calculate distance to high/low lines:
21812 double keyPixel = keyAxis->coordToPixel(it.value().key);
21313 double keyPixel = keyAxis->coordToPixel(it.value().key);
21813 double highLineDistSqr = distSqrToLine(QPointF(keyPixel, valueAxis->coordToPixel(it.value().high)), QPointF(keyPixel, valueAxis->coordToPixel(qMax(it.value().open, it.value().close))), pos);
21314 double highLineDistSqr = distSqrToLine(QPointF(keyPixel, valueAxis->coordToPixel(it.value().high)), QPointF(keyPixel, valueAxis->coordToPixel(qMax(it.value().open, it.value().close))), pos);
21814 double lowLineDistSqr = distSqrToLine(QPointF(keyPixel, valueAxis->coordToPixel(it.value().low)), QPointF(keyPixel, valueAxis->coordToPixel(qMin(it.value().open, it.value().close))), pos);
21315 double lowLineDistSqr = distSqrToLine(QPointF(keyPixel, valueAxis->coordToPixel(it.value().low)), QPointF(keyPixel, valueAxis->coordToPixel(qMin(it.value().open, it.value().close))), pos);
21815 currentDistSqr = qMin(highLineDistSqr, lowLineDistSqr);
21316 currentDistSqr = qMin(highLineDistSqr, lowLineDistSqr);
21816 }
21317 }
21817 if (currentDistSqr < minDistSqr)
21318 if (currentDistSqr < minDistSqr)
21818 minDistSqr = currentDistSqr;
21319 minDistSqr = currentDistSqr;
21819 }
21320 }
21820 } else // keyAxis->orientation() == Qt::Vertical
21321 } else // keyAxis->orientation() == Qt::Vertical
21821 {
21322 {
21822 for (it = begin; it != end; ++it)
21323 for (it = begin; it != end; ++it)
21823 {
21324 {
21824 double currentDistSqr;
21325 double currentDistSqr;
21825 // determine whether pos is in open-close-box:
21326 // determine whether pos is in open-close-box:
21826 QCPRange boxKeyRange(it.value().key-mWidth*0.5, it.value().key+mWidth*0.5);
21327 QCPRange boxKeyRange(it.value().key-mWidth*0.5, it.value().key+mWidth*0.5);
21827 QCPRange boxValueRange(it.value().close, it.value().open);
21328 QCPRange boxValueRange(it.value().close, it.value().open);
21828 double posKey, posValue;
21329 double posKey, posValue;
21829 pixelsToCoords(pos, posKey, posValue);
21330 pixelsToCoords(pos, posKey, posValue);
21830 if (boxKeyRange.contains(posKey) && boxValueRange.contains(posValue)) // is in open-close-box
21331 if (boxKeyRange.contains(posKey) && boxValueRange.contains(posValue)) // is in open-close-box
21831 {
21332 {
21832 currentDistSqr = mParentPlot->selectionTolerance()*0.99 * mParentPlot->selectionTolerance()*0.99;
21333 currentDistSqr = mParentPlot->selectionTolerance()*0.99 * mParentPlot->selectionTolerance()*0.99;
21833 } else
21334 } else
21834 {
21335 {
21835 // calculate distance to high/low lines:
21336 // calculate distance to high/low lines:
21836 double keyPixel = keyAxis->coordToPixel(it.value().key);
21337 double keyPixel = keyAxis->coordToPixel(it.value().key);
21837 double highLineDistSqr = distSqrToLine(QPointF(valueAxis->coordToPixel(it.value().high), keyPixel), QPointF(valueAxis->coordToPixel(qMax(it.value().open, it.value().close)), keyPixel), pos);
21338 double highLineDistSqr = distSqrToLine(QPointF(valueAxis->coordToPixel(it.value().high), keyPixel), QPointF(valueAxis->coordToPixel(qMax(it.value().open, it.value().close)), keyPixel), pos);
21838 double lowLineDistSqr = distSqrToLine(QPointF(valueAxis->coordToPixel(it.value().low), keyPixel), QPointF(valueAxis->coordToPixel(qMin(it.value().open, it.value().close)), keyPixel), pos);
21339 double lowLineDistSqr = distSqrToLine(QPointF(valueAxis->coordToPixel(it.value().low), keyPixel), QPointF(valueAxis->coordToPixel(qMin(it.value().open, it.value().close)), keyPixel), pos);
21839 currentDistSqr = qMin(highLineDistSqr, lowLineDistSqr);
21340 currentDistSqr = qMin(highLineDistSqr, lowLineDistSqr);
21840 }
21341 }
21841 if (currentDistSqr < minDistSqr)
21342 if (currentDistSqr < minDistSqr)
21842 minDistSqr = currentDistSqr;
21343 minDistSqr = currentDistSqr;
21843 }
21344 }
21844 }
21345 }
21845 return qSqrt(minDistSqr);
21346 return qSqrt(minDistSqr);
21846 }
21347 }
21847
21348
21848 /*! \internal
21349 /*! \internal
@@ -21863,22 +21364,22 double QCPFinancial::candlestickSelectTe
21863 */
21364 */
21864 void QCPFinancial::getVisibleDataBounds(QCPFinancialDataMap::const_iterator &lower, QCPFinancialDataMap::const_iterator &upper) const
21365 void QCPFinancial::getVisibleDataBounds(QCPFinancialDataMap::const_iterator &lower, QCPFinancialDataMap::const_iterator &upper) const
21865 {
21366 {
21866 if (!mKeyAxis) { qDebug() << Q_FUNC_INFO << "invalid key axis"; return; }
21367 if (!mKeyAxis) { qDebug() << Q_FUNC_INFO << "invalid key axis"; return; }
21867 if (mData->isEmpty())
21368 if (mData->isEmpty())
21868 {
21369 {
21869 lower = mData->constEnd();
21370 lower = mData->constEnd();
21870 upper = mData->constEnd();
21371 upper = mData->constEnd();
21871 return;
21372 return;
21872 }
21373 }
21873
21374
21874 // get visible data range as QMap iterators
21375 // get visible data range as QMap iterators
21875 QCPFinancialDataMap::const_iterator lbound = mData->lowerBound(mKeyAxis.data()->range().lower);
21376 QCPFinancialDataMap::const_iterator lbound = mData->lowerBound(mKeyAxis.data()->range().lower);
21876 QCPFinancialDataMap::const_iterator ubound = mData->upperBound(mKeyAxis.data()->range().upper);
21377 QCPFinancialDataMap::const_iterator ubound = mData->upperBound(mKeyAxis.data()->range().upper);
21877 bool lowoutlier = lbound != mData->constBegin(); // indicates whether there exist points below axis range
21378 bool lowoutlier = lbound != mData->constBegin(); // indicates whether there exist points below axis range
21878 bool highoutlier = ubound != mData->constEnd(); // indicates whether there exist points above axis range
21379 bool highoutlier = ubound != mData->constEnd(); // indicates whether there exist points above axis range
21879
21380
21880 lower = (lowoutlier ? lbound-1 : lbound); // data point range that will be actually drawn
21381 lower = (lowoutlier ? lbound-1 : lbound); // data point range that will be actually drawn
21881 upper = (highoutlier ? ubound : ubound-1); // data point range that will be actually drawn
21382 upper = (highoutlier ? ubound : ubound-1); // data point range that will be actually drawn
21882 }
21383 }
21883
21384
21884
21385
@@ -21900,15 +21401,15 void QCPFinancial::getVisibleDataBounds(
21900 The constructed item can be added to the plot with QCustomPlot::addItem.
21401 The constructed item can be added to the plot with QCustomPlot::addItem.
21901 */
21402 */
21902 QCPItemStraightLine::QCPItemStraightLine(QCustomPlot *parentPlot) :
21403 QCPItemStraightLine::QCPItemStraightLine(QCustomPlot *parentPlot) :
21903 QCPAbstractItem(parentPlot),
21404 QCPAbstractItem(parentPlot),
21904 point1(createPosition(QLatin1String("point1"))),
21405 point1(createPosition(QLatin1String("point1"))),
21905 point2(createPosition(QLatin1String("point2")))
21406 point2(createPosition(QLatin1String("point2")))
21906 {
21407 {
21907 point1->setCoords(0, 0);
21408 point1->setCoords(0, 0);
21908 point2->setCoords(1, 1);
21409 point2->setCoords(1, 1);
21909
21410
21910 setPen(QPen(Qt::black));
21411 setPen(QPen(Qt::black));
21911 setSelectedPen(QPen(Qt::blue,2));
21412 setSelectedPen(QPen(Qt::blue,2));
21912 }
21413 }
21913
21414
21914 QCPItemStraightLine::~QCPItemStraightLine()
21415 QCPItemStraightLine::~QCPItemStraightLine()
@@ -21922,7 +21423,7 QCPItemStraightLine::~QCPItemStraightLin
21922 */
21423 */
21923 void QCPItemStraightLine::setPen(const QPen &pen)
21424 void QCPItemStraightLine::setPen(const QPen &pen)
21924 {
21425 {
21925 mPen = pen;
21426 mPen = pen;
21926 }
21427 }
21927
21428
21928 /*!
21429 /*!
@@ -21932,32 +21433,32 void QCPItemStraightLine::setPen(const Q
21932 */
21433 */
21933 void QCPItemStraightLine::setSelectedPen(const QPen &pen)
21434 void QCPItemStraightLine::setSelectedPen(const QPen &pen)
21934 {
21435 {
21935 mSelectedPen = pen;
21436 mSelectedPen = pen;
21936 }
21437 }
21937
21438
21938 /* inherits documentation from base class */
21439 /* inherits documentation from base class */
21939 double QCPItemStraightLine::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
21440 double QCPItemStraightLine::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
21940 {
21441 {
21941 Q_UNUSED(details)
21442 Q_UNUSED(details)
21942 if (onlySelectable && !mSelectable)
21443 if (onlySelectable && !mSelectable)
21943 return -1;
21444 return -1;
21944
21445
21945 return distToStraightLine(QVector2D(point1->pixelPoint()), QVector2D(point2->pixelPoint()-point1->pixelPoint()), QVector2D(pos));
21446 return distToStraightLine(QVector2D(point1->pixelPoint()), QVector2D(point2->pixelPoint()-point1->pixelPoint()), QVector2D(pos));
21946 }
21447 }
21947
21448
21948 /* inherits documentation from base class */
21449 /* inherits documentation from base class */
21949 void QCPItemStraightLine::draw(QCPPainter *painter)
21450 void QCPItemStraightLine::draw(QCPPainter *painter)
21950 {
21451 {
21951 QVector2D start(point1->pixelPoint());
21452 QVector2D start(point1->pixelPoint());
21952 QVector2D end(point2->pixelPoint());
21453 QVector2D end(point2->pixelPoint());
21953 // get visible segment of straight line inside clipRect:
21454 // get visible segment of straight line inside clipRect:
21954 double clipPad = mainPen().widthF();
21455 double clipPad = mainPen().widthF();
21955 QLineF line = getRectClippedStraightLine(start, end-start, clipRect().adjusted(-clipPad, -clipPad, clipPad, clipPad));
21456 QLineF line = getRectClippedStraightLine(start, end-start, clipRect().adjusted(-clipPad, -clipPad, clipPad, clipPad));
21956 // paint visible segment, if existent:
21457 // paint visible segment, if existent:
21957 if (!line.isNull())
21458 if (!line.isNull())
21958 {
21459 {
21959 painter->setPen(mainPen());
21460 painter->setPen(mainPen());
21960 painter->drawLine(line);
21461 painter->drawLine(line);
21961 }
21462 }
21962 }
21463 }
21963
21464
@@ -21970,7 +21471,7 void QCPItemStraightLine::draw(QCPPainte
21970 */
21471 */
21971 double QCPItemStraightLine::distToStraightLine(const QVector2D &base, const QVector2D &vec, const QVector2D &point) const
21472 double QCPItemStraightLine::distToStraightLine(const QVector2D &base, const QVector2D &vec, const QVector2D &point) const
21972 {
21473 {
21973 return qAbs((base.y()-point.y())*vec.x()-(base.x()-point.x())*vec.y())/vec.length();
21474 return qAbs((base.y()-point.y())*vec.x()-(base.x()-point.x())*vec.y())/vec.length();
21974 }
21475 }
21975
21476
21976 /*! \internal
21477 /*! \internal
@@ -21982,81 +21483,81 double QCPItemStraightLine::distToStraig
21982 */
21483 */
21983 QLineF QCPItemStraightLine::getRectClippedStraightLine(const QVector2D &base, const QVector2D &vec, const QRect &rect) const
21484 QLineF QCPItemStraightLine::getRectClippedStraightLine(const QVector2D &base, const QVector2D &vec, const QRect &rect) const
21984 {
21485 {
21985 double bx, by;
21486 double bx, by;
21986 double gamma;
21487 double gamma;
21987 QLineF result;
21488 QLineF result;
21988 if (vec.x() == 0 && vec.y() == 0)
21489 if (vec.x() == 0 && vec.y() == 0)
21989 return result;
21490 return result;
21990 if (qFuzzyIsNull(vec.x())) // line is vertical
21491 if (qFuzzyIsNull(vec.x())) // line is vertical
21991 {
21492 {
21992 // check top of rect:
21493 // check top of rect:
21993 bx = rect.left();
21494 bx = rect.left();
21994 by = rect.top();
21495 by = rect.top();
21995 gamma = base.x()-bx + (by-base.y())*vec.x()/vec.y();
21496 gamma = base.x()-bx + (by-base.y())*vec.x()/vec.y();
21996 if (gamma >= 0 && gamma <= rect.width())
21497 if (gamma >= 0 && gamma <= rect.width())
21997 result.setLine(bx+gamma, rect.top(), bx+gamma, rect.bottom()); // no need to check bottom because we know line is vertical
21498 result.setLine(bx+gamma, rect.top(), bx+gamma, rect.bottom()); // no need to check bottom because we know line is vertical
21998 } else if (qFuzzyIsNull(vec.y())) // line is horizontal
21499 } else if (qFuzzyIsNull(vec.y())) // line is horizontal
21999 {
21500 {
22000 // check left of rect:
21501 // check left of rect:
22001 bx = rect.left();
21502 bx = rect.left();
22002 by = rect.top();
21503 by = rect.top();
22003 gamma = base.y()-by + (bx-base.x())*vec.y()/vec.x();
21504 gamma = base.y()-by + (bx-base.x())*vec.y()/vec.x();
22004 if (gamma >= 0 && gamma <= rect.height())
21505 if (gamma >= 0 && gamma <= rect.height())
22005 result.setLine(rect.left(), by+gamma, rect.right(), by+gamma); // no need to check right because we know line is horizontal
21506 result.setLine(rect.left(), by+gamma, rect.right(), by+gamma); // no need to check right because we know line is horizontal
22006 } else // line is skewed
21507 } else // line is skewed
22007 {
21508 {
22008 QList<QVector2D> pointVectors;
21509 QList<QVector2D> pointVectors;
22009 // check top of rect:
21510 // check top of rect:
22010 bx = rect.left();
21511 bx = rect.left();
22011 by = rect.top();
21512 by = rect.top();
22012 gamma = base.x()-bx + (by-base.y())*vec.x()/vec.y();
21513 gamma = base.x()-bx + (by-base.y())*vec.x()/vec.y();
22013 if (gamma >= 0 && gamma <= rect.width())
21514 if (gamma >= 0 && gamma <= rect.width())
22014 pointVectors.append(QVector2D(bx+gamma, by));
21515 pointVectors.append(QVector2D(bx+gamma, by));
22015 // check bottom of rect:
21516 // check bottom of rect:
22016 bx = rect.left();
21517 bx = rect.left();
22017 by = rect.bottom();
21518 by = rect.bottom();
22018 gamma = base.x()-bx + (by-base.y())*vec.x()/vec.y();
21519 gamma = base.x()-bx + (by-base.y())*vec.x()/vec.y();
22019 if (gamma >= 0 && gamma <= rect.width())
21520 if (gamma >= 0 && gamma <= rect.width())
22020 pointVectors.append(QVector2D(bx+gamma, by));
21521 pointVectors.append(QVector2D(bx+gamma, by));
22021 // check left of rect:
21522 // check left of rect:
22022 bx = rect.left();
21523 bx = rect.left();
22023 by = rect.top();
21524 by = rect.top();
22024 gamma = base.y()-by + (bx-base.x())*vec.y()/vec.x();
21525 gamma = base.y()-by + (bx-base.x())*vec.y()/vec.x();
22025 if (gamma >= 0 && gamma <= rect.height())
21526 if (gamma >= 0 && gamma <= rect.height())
22026 pointVectors.append(QVector2D(bx, by+gamma));
21527 pointVectors.append(QVector2D(bx, by+gamma));
22027 // check right of rect:
21528 // check right of rect:
22028 bx = rect.right();
21529 bx = rect.right();
22029 by = rect.top();
21530 by = rect.top();
22030 gamma = base.y()-by + (bx-base.x())*vec.y()/vec.x();
21531 gamma = base.y()-by + (bx-base.x())*vec.y()/vec.x();
22031 if (gamma >= 0 && gamma <= rect.height())
21532 if (gamma >= 0 && gamma <= rect.height())
22032 pointVectors.append(QVector2D(bx, by+gamma));
21533 pointVectors.append(QVector2D(bx, by+gamma));
22033
21534
22034 // evaluate points:
21535 // evaluate points:
22035 if (pointVectors.size() == 2)
21536 if (pointVectors.size() == 2)
22036 {
21537 {
22037 result.setPoints(pointVectors.at(0).toPointF(), pointVectors.at(1).toPointF());
21538 result.setPoints(pointVectors.at(0).toPointF(), pointVectors.at(1).toPointF());
22038 } else if (pointVectors.size() > 2)
21539 } else if (pointVectors.size() > 2)
22039 {
21540 {
22040 // line probably goes through corner of rect, and we got two points there. single out the point pair with greatest distance:
21541 // line probably goes through corner of rect, and we got two points there. single out the point pair with greatest distance:
22041 double distSqrMax = 0;
21542 double distSqrMax = 0;
22042 QVector2D pv1, pv2;
21543 QVector2D pv1, pv2;
22043 for (int i=0; i<pointVectors.size()-1; ++i)
21544 for (int i=0; i<pointVectors.size()-1; ++i)
22044 {
21545 {
22045 for (int k=i+1; k<pointVectors.size(); ++k)
21546 for (int k=i+1; k<pointVectors.size(); ++k)
22046 {
21547 {
22047 double distSqr = (pointVectors.at(i)-pointVectors.at(k)).lengthSquared();
21548 double distSqr = (pointVectors.at(i)-pointVectors.at(k)).lengthSquared();
22048 if (distSqr > distSqrMax)
21549 if (distSqr > distSqrMax)
22049 {
21550 {
22050 pv1 = pointVectors.at(i);
21551 pv1 = pointVectors.at(i);
22051 pv2 = pointVectors.at(k);
21552 pv2 = pointVectors.at(k);
22052 distSqrMax = distSqr;
21553 distSqrMax = distSqr;
22053 }
21554 }
22054 }
21555 }
22055 }
21556 }
22056 result.setPoints(pv1.toPointF(), pv2.toPointF());
21557 result.setPoints(pv1.toPointF(), pv2.toPointF());
22057 }
21558 }
22058 }
21559 }
22059 return result;
21560 return result;
22060 }
21561 }
22061
21562
22062 /*! \internal
21563 /*! \internal
@@ -22066,7 +21567,7 QLineF QCPItemStraightLine::getRectClipp
22066 */
21567 */
22067 QPen QCPItemStraightLine::mainPen() const
21568 QPen QCPItemStraightLine::mainPen() const
22068 {
21569 {
22069 return mSelected ? mSelectedPen : mPen;
21570 return mSelected ? mSelectedPen : mPen;
22070 }
21571 }
22071
21572
22072
21573
@@ -22090,15 +21591,15 QPen QCPItemStraightLine::mainPen() cons
22090 The constructed item can be added to the plot with QCustomPlot::addItem.
21591 The constructed item can be added to the plot with QCustomPlot::addItem.
22091 */
21592 */
22092 QCPItemLine::QCPItemLine(QCustomPlot *parentPlot) :
21593 QCPItemLine::QCPItemLine(QCustomPlot *parentPlot) :
22093 QCPAbstractItem(parentPlot),
21594 QCPAbstractItem(parentPlot),
22094 start(createPosition(QLatin1String("start"))),
21595 start(createPosition(QLatin1String("start"))),
22095 end(createPosition(QLatin1String("end")))
21596 end(createPosition(QLatin1String("end")))
22096 {
21597 {
22097 start->setCoords(0, 0);
21598 start->setCoords(0, 0);
22098 end->setCoords(1, 1);
21599 end->setCoords(1, 1);
22099
21600
22100 setPen(QPen(Qt::black));
21601 setPen(QPen(Qt::black));
22101 setSelectedPen(QPen(Qt::blue,2));
21602 setSelectedPen(QPen(Qt::blue,2));
22102 }
21603 }
22103
21604
22104 QCPItemLine::~QCPItemLine()
21605 QCPItemLine::~QCPItemLine()
@@ -22112,7 +21613,7 QCPItemLine::~QCPItemLine()
22112 */
21613 */
22113 void QCPItemLine::setPen(const QPen &pen)
21614 void QCPItemLine::setPen(const QPen &pen)
22114 {
21615 {
22115 mPen = pen;
21616 mPen = pen;
22116 }
21617 }
22117
21618
22118 /*!
21619 /*!
@@ -22122,7 +21623,7 void QCPItemLine::setPen(const QPen &pen
22122 */
21623 */
22123 void QCPItemLine::setSelectedPen(const QPen &pen)
21624 void QCPItemLine::setSelectedPen(const QPen &pen)
22124 {
21625 {
22125 mSelectedPen = pen;
21626 mSelectedPen = pen;
22126 }
21627 }
22127
21628
22128 /*!
21629 /*!
@@ -22135,7 +21636,7 void QCPItemLine::setSelectedPen(const Q
22135 */
21636 */
22136 void QCPItemLine::setHead(const QCPLineEnding &head)
21637 void QCPItemLine::setHead(const QCPLineEnding &head)
22137 {
21638 {
22138 mHead = head;
21639 mHead = head;
22139 }
21640 }
22140
21641
22141 /*!
21642 /*!
@@ -22148,40 +21649,40 void QCPItemLine::setHead(const QCPLineE
22148 */
21649 */
22149 void QCPItemLine::setTail(const QCPLineEnding &tail)
21650 void QCPItemLine::setTail(const QCPLineEnding &tail)
22150 {
21651 {
22151 mTail = tail;
21652 mTail = tail;
22152 }
21653 }
22153
21654
22154 /* inherits documentation from base class */
21655 /* inherits documentation from base class */
22155 double QCPItemLine::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
21656 double QCPItemLine::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
22156 {
21657 {
22157 Q_UNUSED(details)
21658 Q_UNUSED(details)
22158 if (onlySelectable && !mSelectable)
21659 if (onlySelectable && !mSelectable)
22159 return -1;
21660 return -1;
22160
21661
22161 return qSqrt(distSqrToLine(start->pixelPoint(), end->pixelPoint(), pos));
21662 return qSqrt(distSqrToLine(start->pixelPoint(), end->pixelPoint(), pos));
22162 }
21663 }
22163
21664
22164 /* inherits documentation from base class */
21665 /* inherits documentation from base class */
22165 void QCPItemLine::draw(QCPPainter *painter)
21666 void QCPItemLine::draw(QCPPainter *painter)
22166 {
21667 {
22167 QVector2D startVec(start->pixelPoint());
21668 QVector2D startVec(start->pixelPoint());
22168 QVector2D endVec(end->pixelPoint());
21669 QVector2D endVec(end->pixelPoint());
22169 if (startVec.toPoint() == endVec.toPoint())
21670 if (startVec.toPoint() == endVec.toPoint())
22170 return;
21671 return;
22171 // get visible segment of straight line inside clipRect:
21672 // get visible segment of straight line inside clipRect:
22172 double clipPad = qMax(mHead.boundingDistance(), mTail.boundingDistance());
21673 double clipPad = qMax(mHead.boundingDistance(), mTail.boundingDistance());
22173 clipPad = qMax(clipPad, (double)mainPen().widthF());
21674 clipPad = qMax(clipPad, (double)mainPen().widthF());
22174 QLineF line = getRectClippedLine(startVec, endVec, clipRect().adjusted(-clipPad, -clipPad, clipPad, clipPad));
21675 QLineF line = getRectClippedLine(startVec, endVec, clipRect().adjusted(-clipPad, -clipPad, clipPad, clipPad));
22175 // paint visible segment, if existent:
21676 // paint visible segment, if existent:
22176 if (!line.isNull())
21677 if (!line.isNull())
22177 {
21678 {
22178 painter->setPen(mainPen());
21679 painter->setPen(mainPen());
22179 painter->drawLine(line);
21680 painter->drawLine(line);
22180 painter->setBrush(Qt::SolidPattern);
21681 painter->setBrush(Qt::SolidPattern);
22181 if (mTail.style() != QCPLineEnding::esNone)
21682 if (mTail.style() != QCPLineEnding::esNone)
22182 mTail.draw(painter, startVec, startVec-endVec);
21683 mTail.draw(painter, startVec, startVec-endVec);
22183 if (mHead.style() != QCPLineEnding::esNone)
21684 if (mHead.style() != QCPLineEnding::esNone)
22184 mHead.draw(painter, endVec, endVec-startVec);
21685 mHead.draw(painter, endVec, endVec-startVec);
22185 }
21686 }
22186 }
21687 }
22187
21688
@@ -22194,95 +21695,95 void QCPItemLine::draw(QCPPainter *paint
22194 */
21695 */
22195 QLineF QCPItemLine::getRectClippedLine(const QVector2D &start, const QVector2D &end, const QRect &rect) const
21696 QLineF QCPItemLine::getRectClippedLine(const QVector2D &start, const QVector2D &end, const QRect &rect) const
22196 {
21697 {
22197 bool containsStart = rect.contains(start.x(), start.y());
21698 bool containsStart = rect.contains(start.x(), start.y());
22198 bool containsEnd = rect.contains(end.x(), end.y());
21699 bool containsEnd = rect.contains(end.x(), end.y());
22199 if (containsStart && containsEnd)
21700 if (containsStart && containsEnd)
22200 return QLineF(start.toPointF(), end.toPointF());
21701 return QLineF(start.toPointF(), end.toPointF());
22201
21702
22202 QVector2D base = start;
21703 QVector2D base = start;
22203 QVector2D vec = end-start;
21704 QVector2D vec = end-start;
22204 double bx, by;
21705 double bx, by;
22205 double gamma, mu;
21706 double gamma, mu;
22206 QLineF result;
21707 QLineF result;
22207 QList<QVector2D> pointVectors;
21708 QList<QVector2D> pointVectors;
22208
21709
22209 if (!qFuzzyIsNull(vec.y())) // line is not horizontal
21710 if (!qFuzzyIsNull(vec.y())) // line is not horizontal
22210 {
21711 {
22211 // check top of rect:
21712 // check top of rect:
22212 bx = rect.left();
21713 bx = rect.left();
22213 by = rect.top();
21714 by = rect.top();
22214 mu = (by-base.y())/vec.y();
21715 mu = (by-base.y())/vec.y();
22215 if (mu >= 0 && mu <= 1)
21716 if (mu >= 0 && mu <= 1)
22216 {
21717 {
22217 gamma = base.x()-bx + mu*vec.x();
21718 gamma = base.x()-bx + mu*vec.x();
22218 if (gamma >= 0 && gamma <= rect.width())
21719 if (gamma >= 0 && gamma <= rect.width())
22219 pointVectors.append(QVector2D(bx+gamma, by));
21720 pointVectors.append(QVector2D(bx+gamma, by));
22220 }
21721 }
22221 // check bottom of rect:
21722 // check bottom of rect:
22222 bx = rect.left();
21723 bx = rect.left();
22223 by = rect.bottom();
21724 by = rect.bottom();
22224 mu = (by-base.y())/vec.y();
21725 mu = (by-base.y())/vec.y();
22225 if (mu >= 0 && mu <= 1)
21726 if (mu >= 0 && mu <= 1)
22226 {
21727 {
22227 gamma = base.x()-bx + mu*vec.x();
21728 gamma = base.x()-bx + mu*vec.x();
22228 if (gamma >= 0 && gamma <= rect.width())
21729 if (gamma >= 0 && gamma <= rect.width())
22229 pointVectors.append(QVector2D(bx+gamma, by));
21730 pointVectors.append(QVector2D(bx+gamma, by));
22230 }
21731 }
22231 }
21732 }
22232 if (!qFuzzyIsNull(vec.x())) // line is not vertical
21733 if (!qFuzzyIsNull(vec.x())) // line is not vertical
22233 {
21734 {
22234 // check left of rect:
21735 // check left of rect:
22235 bx = rect.left();
21736 bx = rect.left();
22236 by = rect.top();
21737 by = rect.top();
22237 mu = (bx-base.x())/vec.x();
21738 mu = (bx-base.x())/vec.x();
22238 if (mu >= 0 && mu <= 1)
21739 if (mu >= 0 && mu <= 1)
22239 {
21740 {
22240 gamma = base.y()-by + mu*vec.y();
21741 gamma = base.y()-by + mu*vec.y();
22241 if (gamma >= 0 && gamma <= rect.height())
21742 if (gamma >= 0 && gamma <= rect.height())
22242 pointVectors.append(QVector2D(bx, by+gamma));
21743 pointVectors.append(QVector2D(bx, by+gamma));
22243 }
21744 }
22244 // check right of rect:
21745 // check right of rect:
22245 bx = rect.right();
21746 bx = rect.right();
22246 by = rect.top();
21747 by = rect.top();
22247 mu = (bx-base.x())/vec.x();
21748 mu = (bx-base.x())/vec.x();
22248 if (mu >= 0 && mu <= 1)
21749 if (mu >= 0 && mu <= 1)
22249 {
21750 {
22250 gamma = base.y()-by + mu*vec.y();
21751 gamma = base.y()-by + mu*vec.y();
22251 if (gamma >= 0 && gamma <= rect.height())
21752 if (gamma >= 0 && gamma <= rect.height())
22252 pointVectors.append(QVector2D(bx, by+gamma));
21753 pointVectors.append(QVector2D(bx, by+gamma));
22253 }
21754 }
22254 }
21755 }
22255
21756
22256 if (containsStart)
21757 if (containsStart)
22257 pointVectors.append(start);
21758 pointVectors.append(start);
22258 if (containsEnd)
21759 if (containsEnd)
22259 pointVectors.append(end);
21760 pointVectors.append(end);
22260
21761
22261 // evaluate points:
21762 // evaluate points:
22262 if (pointVectors.size() == 2)
21763 if (pointVectors.size() == 2)
22263 {
21764 {
22264 result.setPoints(pointVectors.at(0).toPointF(), pointVectors.at(1).toPointF());
21765 result.setPoints(pointVectors.at(0).toPointF(), pointVectors.at(1).toPointF());
22265 } else if (pointVectors.size() > 2)
21766 } else if (pointVectors.size() > 2)
22266 {
21767 {
22267 // line probably goes through corner of rect, and we got two points there. single out the point pair with greatest distance:
21768 // line probably goes through corner of rect, and we got two points there. single out the point pair with greatest distance:
22268 double distSqrMax = 0;
21769 double distSqrMax = 0;
22269 QVector2D pv1, pv2;
21770 QVector2D pv1, pv2;
22270 for (int i=0; i<pointVectors.size()-1; ++i)
21771 for (int i=0; i<pointVectors.size()-1; ++i)
22271 {
21772 {
22272 for (int k=i+1; k<pointVectors.size(); ++k)
21773 for (int k=i+1; k<pointVectors.size(); ++k)
22273 {
21774 {
22274 double distSqr = (pointVectors.at(i)-pointVectors.at(k)).lengthSquared();
21775 double distSqr = (pointVectors.at(i)-pointVectors.at(k)).lengthSquared();
22275 if (distSqr > distSqrMax)
21776 if (distSqr > distSqrMax)
22276 {
21777 {
22277 pv1 = pointVectors.at(i);
21778 pv1 = pointVectors.at(i);
22278 pv2 = pointVectors.at(k);
21779 pv2 = pointVectors.at(k);
22279 distSqrMax = distSqr;
21780 distSqrMax = distSqr;
22280 }
21781 }
22281 }
21782 }
22282 }
21783 }
22283 result.setPoints(pv1.toPointF(), pv2.toPointF());
21784 result.setPoints(pv1.toPointF(), pv2.toPointF());
22284 }
21785 }
22285 return result;
21786 return result;
22286 }
21787 }
22287
21788
22288 /*! \internal
21789 /*! \internal
@@ -22292,7 +21793,7 QLineF QCPItemLine::getRectClippedLine(c
22292 */
21793 */
22293 QPen QCPItemLine::mainPen() const
21794 QPen QCPItemLine::mainPen() const
22294 {
21795 {
22295 return mSelected ? mSelectedPen : mPen;
21796 return mSelected ? mSelectedPen : mPen;
22296 }
21797 }
22297
21798
22298
21799
@@ -22323,19 +21824,19 QPen QCPItemLine::mainPen() const
22323 The constructed item can be added to the plot with QCustomPlot::addItem.
21824 The constructed item can be added to the plot with QCustomPlot::addItem.
22324 */
21825 */
22325 QCPItemCurve::QCPItemCurve(QCustomPlot *parentPlot) :
21826 QCPItemCurve::QCPItemCurve(QCustomPlot *parentPlot) :
22326 QCPAbstractItem(parentPlot),
21827 QCPAbstractItem(parentPlot),
22327 start(createPosition(QLatin1String("start"))),
21828 start(createPosition(QLatin1String("start"))),
22328 startDir(createPosition(QLatin1String("startDir"))),
21829 startDir(createPosition(QLatin1String("startDir"))),
22329 endDir(createPosition(QLatin1String("endDir"))),
21830 endDir(createPosition(QLatin1String("endDir"))),
22330 end(createPosition(QLatin1String("end")))
21831 end(createPosition(QLatin1String("end")))
22331 {
21832 {
22332 start->setCoords(0, 0);
21833 start->setCoords(0, 0);
22333 startDir->setCoords(0.5, 0);
21834 startDir->setCoords(0.5, 0);
22334 endDir->setCoords(0, 0.5);
21835 endDir->setCoords(0, 0.5);
22335 end->setCoords(1, 1);
21836 end->setCoords(1, 1);
22336
21837
22337 setPen(QPen(Qt::black));
21838 setPen(QPen(Qt::black));
22338 setSelectedPen(QPen(Qt::blue,2));
21839 setSelectedPen(QPen(Qt::blue,2));
22339 }
21840 }
22340
21841
22341 QCPItemCurve::~QCPItemCurve()
21842 QCPItemCurve::~QCPItemCurve()
@@ -22349,7 +21850,7 QCPItemCurve::~QCPItemCurve()
22349 */
21850 */
22350 void QCPItemCurve::setPen(const QPen &pen)
21851 void QCPItemCurve::setPen(const QPen &pen)
22351 {
21852 {
22352 mPen = pen;
21853 mPen = pen;
22353 }
21854 }
22354
21855
22355 /*!
21856 /*!
@@ -22359,7 +21860,7 void QCPItemCurve::setPen(const QPen &pe
22359 */
21860 */
22360 void QCPItemCurve::setSelectedPen(const QPen &pen)
21861 void QCPItemCurve::setSelectedPen(const QPen &pen)
22361 {
21862 {
22362 mSelectedPen = pen;
21863 mSelectedPen = pen;
22363 }
21864 }
22364
21865
22365 /*!
21866 /*!
@@ -22372,7 +21873,7 void QCPItemCurve::setSelectedPen(const
22372 */
21873 */
22373 void QCPItemCurve::setHead(const QCPLineEnding &head)
21874 void QCPItemCurve::setHead(const QCPLineEnding &head)
22374 {
21875 {
22375 mHead = head;
21876 mHead = head;
22376 }
21877 }
22377
21878
22378 /*!
21879 /*!
@@ -22385,62 +21886,62 void QCPItemCurve::setHead(const QCPLine
22385 */
21886 */
22386 void QCPItemCurve::setTail(const QCPLineEnding &tail)
21887 void QCPItemCurve::setTail(const QCPLineEnding &tail)
22387 {
21888 {
22388 mTail = tail;
21889 mTail = tail;
22389 }
21890 }
22390
21891
22391 /* inherits documentation from base class */
21892 /* inherits documentation from base class */
22392 double QCPItemCurve::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
21893 double QCPItemCurve::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
22393 {
21894 {
22394 Q_UNUSED(details)
21895 Q_UNUSED(details)
22395 if (onlySelectable && !mSelectable)
21896 if (onlySelectable && !mSelectable)
22396 return -1;
21897 return -1;
22397
21898
22398 QPointF startVec(start->pixelPoint());
21899 QPointF startVec(start->pixelPoint());
22399 QPointF startDirVec(startDir->pixelPoint());
21900 QPointF startDirVec(startDir->pixelPoint());
22400 QPointF endDirVec(endDir->pixelPoint());
21901 QPointF endDirVec(endDir->pixelPoint());
22401 QPointF endVec(end->pixelPoint());
21902 QPointF endVec(end->pixelPoint());
22402
21903
22403 QPainterPath cubicPath(startVec);
21904 QPainterPath cubicPath(startVec);
22404 cubicPath.cubicTo(startDirVec, endDirVec, endVec);
21905 cubicPath.cubicTo(startDirVec, endDirVec, endVec);
22405
21906
22406 QPolygonF polygon = cubicPath.toSubpathPolygons().first();
21907 QPolygonF polygon = cubicPath.toSubpathPolygons().first();
22407 double minDistSqr = std::numeric_limits<double>::max();
21908 double minDistSqr = std::numeric_limits<double>::max();
22408 for (int i=1; i<polygon.size(); ++i)
21909 for (int i=1; i<polygon.size(); ++i)
22409 {
21910 {
22410 double distSqr = distSqrToLine(polygon.at(i-1), polygon.at(i), pos);
21911 double distSqr = distSqrToLine(polygon.at(i-1), polygon.at(i), pos);
22411 if (distSqr < minDistSqr)
21912 if (distSqr < minDistSqr)
22412 minDistSqr = distSqr;
21913 minDistSqr = distSqr;
22413 }
21914 }
22414 return qSqrt(minDistSqr);
21915 return qSqrt(minDistSqr);
22415 }
21916 }
22416
21917
22417 /* inherits documentation from base class */
21918 /* inherits documentation from base class */
22418 void QCPItemCurve::draw(QCPPainter *painter)
21919 void QCPItemCurve::draw(QCPPainter *painter)
22419 {
21920 {
22420 QPointF startVec(start->pixelPoint());
21921 QPointF startVec(start->pixelPoint());
22421 QPointF startDirVec(startDir->pixelPoint());
21922 QPointF startDirVec(startDir->pixelPoint());
22422 QPointF endDirVec(endDir->pixelPoint());
21923 QPointF endDirVec(endDir->pixelPoint());
22423 QPointF endVec(end->pixelPoint());
21924 QPointF endVec(end->pixelPoint());
22424 if (QVector2D(endVec-startVec).length() > 1e10f) // too large curves cause crash
21925 if (QVector2D(endVec-startVec).length() > 1e10f) // too large curves cause crash
22425 return;
21926 return;
22426
21927
22427 QPainterPath cubicPath(startVec);
21928 QPainterPath cubicPath(startVec);
22428 cubicPath.cubicTo(startDirVec, endDirVec, endVec);
21929 cubicPath.cubicTo(startDirVec, endDirVec, endVec);
22429
21930
22430 // paint visible segment, if existent:
21931 // paint visible segment, if existent:
22431 QRect clip = clipRect().adjusted(-mainPen().widthF(), -mainPen().widthF(), mainPen().widthF(), mainPen().widthF());
21932 QRect clip = clipRect().adjusted(-mainPen().widthF(), -mainPen().widthF(), mainPen().widthF(), mainPen().widthF());
22432 QRect cubicRect = cubicPath.controlPointRect().toRect();
21933 QRect cubicRect = cubicPath.controlPointRect().toRect();
22433 if (cubicRect.isEmpty()) // may happen when start and end exactly on same x or y position
21934 if (cubicRect.isEmpty()) // may happen when start and end exactly on same x or y position
22434 cubicRect.adjust(0, 0, 1, 1);
21935 cubicRect.adjust(0, 0, 1, 1);
22435 if (clip.intersects(cubicRect))
21936 if (clip.intersects(cubicRect))
22436 {
21937 {
22437 painter->setPen(mainPen());
21938 painter->setPen(mainPen());
22438 painter->drawPath(cubicPath);
21939 painter->drawPath(cubicPath);
22439 painter->setBrush(Qt::SolidPattern);
21940 painter->setBrush(Qt::SolidPattern);
22440 if (mTail.style() != QCPLineEnding::esNone)
21941 if (mTail.style() != QCPLineEnding::esNone)
22441 mTail.draw(painter, QVector2D(startVec), M_PI-cubicPath.angleAtPercent(0)/180.0*M_PI);
21942 mTail.draw(painter, QVector2D(startVec), M_PI-cubicPath.angleAtPercent(0)/180.0*M_PI);
22442 if (mHead.style() != QCPLineEnding::esNone)
21943 if (mHead.style() != QCPLineEnding::esNone)
22443 mHead.draw(painter, QVector2D(endVec), -cubicPath.angleAtPercent(1)/180.0*M_PI);
21944 mHead.draw(painter, QVector2D(endVec), -cubicPath.angleAtPercent(1)/180.0*M_PI);
22444 }
21945 }
22445 }
21946 }
22446
21947
@@ -22451,7 +21952,7 void QCPItemCurve::draw(QCPPainter *pain
22451 */
21952 */
22452 QPen QCPItemCurve::mainPen() const
21953 QPen QCPItemCurve::mainPen() const
22453 {
21954 {
22454 return mSelected ? mSelectedPen : mPen;
21955 return mSelected ? mSelectedPen : mPen;
22455 }
21956 }
22456
21957
22457
21958
@@ -22473,23 +21974,23 QPen QCPItemCurve::mainPen() const
22473 The constructed item can be added to the plot with QCustomPlot::addItem.
21974 The constructed item can be added to the plot with QCustomPlot::addItem.
22474 */
21975 */
22475 QCPItemRect::QCPItemRect(QCustomPlot *parentPlot) :
21976 QCPItemRect::QCPItemRect(QCustomPlot *parentPlot) :
22476 QCPAbstractItem(parentPlot),
21977 QCPAbstractItem(parentPlot),
22477 topLeft(createPosition(QLatin1String("topLeft"))),
21978 topLeft(createPosition(QLatin1String("topLeft"))),
22478 bottomRight(createPosition(QLatin1String("bottomRight"))),
21979 bottomRight(createPosition(QLatin1String("bottomRight"))),
22479 top(createAnchor(QLatin1String("top"), aiTop)),
21980 top(createAnchor(QLatin1String("top"), aiTop)),
22480 topRight(createAnchor(QLatin1String("topRight"), aiTopRight)),
21981 topRight(createAnchor(QLatin1String("topRight"), aiTopRight)),
22481 right(createAnchor(QLatin1String("right"), aiRight)),
21982 right(createAnchor(QLatin1String("right"), aiRight)),
22482 bottom(createAnchor(QLatin1String("bottom"), aiBottom)),
21983 bottom(createAnchor(QLatin1String("bottom"), aiBottom)),
22483 bottomLeft(createAnchor(QLatin1String("bottomLeft"), aiBottomLeft)),
21984 bottomLeft(createAnchor(QLatin1String("bottomLeft"), aiBottomLeft)),
22484 left(createAnchor(QLatin1String("left"), aiLeft))
21985 left(createAnchor(QLatin1String("left"), aiLeft))
22485 {
21986 {
22486 topLeft->setCoords(0, 1);
21987 topLeft->setCoords(0, 1);
22487 bottomRight->setCoords(1, 0);
21988 bottomRight->setCoords(1, 0);
22488
21989
22489 setPen(QPen(Qt::black));
21990 setPen(QPen(Qt::black));
22490 setSelectedPen(QPen(Qt::blue,2));
21991 setSelectedPen(QPen(Qt::blue,2));
22491 setBrush(Qt::NoBrush);
21992 setBrush(Qt::NoBrush);
22492 setSelectedBrush(Qt::NoBrush);
21993 setSelectedBrush(Qt::NoBrush);
22493 }
21994 }
22494
21995
22495 QCPItemRect::~QCPItemRect()
21996 QCPItemRect::~QCPItemRect()
@@ -22503,7 +22004,7 QCPItemRect::~QCPItemRect()
22503 */
22004 */
22504 void QCPItemRect::setPen(const QPen &pen)
22005 void QCPItemRect::setPen(const QPen &pen)
22505 {
22006 {
22506 mPen = pen;
22007 mPen = pen;
22507 }
22008 }
22508
22009
22509 /*!
22010 /*!
@@ -22513,7 +22014,7 void QCPItemRect::setPen(const QPen &pen
22513 */
22014 */
22514 void QCPItemRect::setSelectedPen(const QPen &pen)
22015 void QCPItemRect::setSelectedPen(const QPen &pen)
22515 {
22016 {
22516 mSelectedPen = pen;
22017 mSelectedPen = pen;
22517 }
22018 }
22518
22019
22519 /*!
22020 /*!
@@ -22524,7 +22025,7 void QCPItemRect::setSelectedPen(const Q
22524 */
22025 */
22525 void QCPItemRect::setBrush(const QBrush &brush)
22026 void QCPItemRect::setBrush(const QBrush &brush)
22526 {
22027 {
22527 mBrush = brush;
22028 mBrush = brush;
22528 }
22029 }
22529
22030
22530 /*!
22031 /*!
@@ -22535,44 +22036,44 void QCPItemRect::setBrush(const QBrush
22535 */
22036 */
22536 void QCPItemRect::setSelectedBrush(const QBrush &brush)
22037 void QCPItemRect::setSelectedBrush(const QBrush &brush)
22537 {
22038 {
22538 mSelectedBrush = brush;
22039 mSelectedBrush = brush;
22539 }
22040 }
22540
22041
22541 /* inherits documentation from base class */
22042 /* inherits documentation from base class */
22542 double QCPItemRect::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
22043 double QCPItemRect::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
22543 {
22044 {
22544 Q_UNUSED(details)
22045 Q_UNUSED(details)
22545 if (onlySelectable && !mSelectable)
22046 if (onlySelectable && !mSelectable)
22546 return -1;
22047 return -1;
22547
22048
22548 QRectF rect = QRectF(topLeft->pixelPoint(), bottomRight->pixelPoint()).normalized();
22049 QRectF rect = QRectF(topLeft->pixelPoint(), bottomRight->pixelPoint()).normalized();
22549 bool filledRect = mBrush.style() != Qt::NoBrush && mBrush.color().alpha() != 0;
22050 bool filledRect = mBrush.style() != Qt::NoBrush && mBrush.color().alpha() != 0;
22550 return rectSelectTest(rect, pos, filledRect);
22051 return rectSelectTest(rect, pos, filledRect);
22551 }
22052 }
22552
22053
22553 /* inherits documentation from base class */
22054 /* inherits documentation from base class */
22554 void QCPItemRect::draw(QCPPainter *painter)
22055 void QCPItemRect::draw(QCPPainter *painter)
22555 {
22056 {
22556 QPointF p1 = topLeft->pixelPoint();
22057 QPointF p1 = topLeft->pixelPoint();
22557 QPointF p2 = bottomRight->pixelPoint();
22058 QPointF p2 = bottomRight->pixelPoint();
22558 if (p1.toPoint() == p2.toPoint())
22059 if (p1.toPoint() == p2.toPoint())
22559 return;
22060 return;
22560 QRectF rect = QRectF(p1, p2).normalized();
22061 QRectF rect = QRectF(p1, p2).normalized();
22561 double clipPad = mainPen().widthF();
22062 double clipPad = mainPen().widthF();
22562 QRectF boundingRect = rect.adjusted(-clipPad, -clipPad, clipPad, clipPad);
22063 QRectF boundingRect = rect.adjusted(-clipPad, -clipPad, clipPad, clipPad);
22563 if (boundingRect.intersects(clipRect())) // only draw if bounding rect of rect item is visible in cliprect
22064 if (boundingRect.intersects(clipRect())) // only draw if bounding rect of rect item is visible in cliprect
22564 {
22065 {
22565 painter->setPen(mainPen());
22066 painter->setPen(mainPen());
22566 painter->setBrush(mainBrush());
22067 painter->setBrush(mainBrush());
22567 painter->drawRect(rect);
22068 painter->drawRect(rect);
22568 }
22069 }
22569 }
22070 }
22570
22071
22571 /* inherits documentation from base class */
22072 /* inherits documentation from base class */
22572 QPointF QCPItemRect::anchorPixelPoint(int anchorId) const
22073 QPointF QCPItemRect::anchorPixelPoint(int anchorId) const
22573 {
22074 {
22574 QRectF rect = QRectF(topLeft->pixelPoint(), bottomRight->pixelPoint());
22075 QRectF rect = QRectF(topLeft->pixelPoint(), bottomRight->pixelPoint());
22575 switch (anchorId)
22076 switch (anchorId)
22576 {
22077 {
22577 case aiTop: return (rect.topLeft()+rect.topRight())*0.5;
22078 case aiTop: return (rect.topLeft()+rect.topRight())*0.5;
22578 case aiTopRight: return rect.topRight();
22079 case aiTopRight: return rect.topRight();
@@ -22581,9 +22082,9 QPointF QCPItemRect::anchorPixelPoint(in
22581 case aiBottomLeft: return rect.bottomLeft();
22082 case aiBottomLeft: return rect.bottomLeft();
22582 case aiLeft: return (rect.topLeft()+rect.bottomLeft())*0.5;
22083 case aiLeft: return (rect.topLeft()+rect.bottomLeft())*0.5;
22583 }
22084 }
22584
22085
22585 qDebug() << Q_FUNC_INFO << "invalid anchorId" << anchorId;
22086 qDebug() << Q_FUNC_INFO << "invalid anchorId" << anchorId;
22586 return QPointF();
22087 return QPointF();
22587 }
22088 }
22588
22089
22589 /*! \internal
22090 /*! \internal
@@ -22593,7 +22094,7 QPointF QCPItemRect::anchorPixelPoint(in
22593 */
22094 */
22594 QPen QCPItemRect::mainPen() const
22095 QPen QCPItemRect::mainPen() const
22595 {
22096 {
22596 return mSelected ? mSelectedPen : mPen;
22097 return mSelected ? mSelectedPen : mPen;
22597 }
22098 }
22598
22099
22599 /*! \internal
22100 /*! \internal
@@ -22603,7 +22104,7 QPen QCPItemRect::mainPen() const
22603 */
22104 */
22604 QBrush QCPItemRect::mainBrush() const
22105 QBrush QCPItemRect::mainBrush() const
22605 {
22106 {
22606 return mSelected ? mSelectedBrush : mBrush;
22107 return mSelected ? mSelectedBrush : mBrush;
22607 }
22108 }
22608
22109
22609
22110
@@ -22631,30 +22132,30 QBrush QCPItemRect::mainBrush() const
22631 The constructed item can be added to the plot with QCustomPlot::addItem.
22132 The constructed item can be added to the plot with QCustomPlot::addItem.
22632 */
22133 */
22633 QCPItemText::QCPItemText(QCustomPlot *parentPlot) :
22134 QCPItemText::QCPItemText(QCustomPlot *parentPlot) :
22634 QCPAbstractItem(parentPlot),
22135 QCPAbstractItem(parentPlot),
22635 position(createPosition(QLatin1String("position"))),
22136 position(createPosition(QLatin1String("position"))),
22636 topLeft(createAnchor(QLatin1String("topLeft"), aiTopLeft)),
22137 topLeft(createAnchor(QLatin1String("topLeft"), aiTopLeft)),
22637 top(createAnchor(QLatin1String("top"), aiTop)),
22138 top(createAnchor(QLatin1String("top"), aiTop)),
22638 topRight(createAnchor(QLatin1String("topRight"), aiTopRight)),
22139 topRight(createAnchor(QLatin1String("topRight"), aiTopRight)),
22639 right(createAnchor(QLatin1String("right"), aiRight)),
22140 right(createAnchor(QLatin1String("right"), aiRight)),
22640 bottomRight(createAnchor(QLatin1String("bottomRight"), aiBottomRight)),
22141 bottomRight(createAnchor(QLatin1String("bottomRight"), aiBottomRight)),
22641 bottom(createAnchor(QLatin1String("bottom"), aiBottom)),
22142 bottom(createAnchor(QLatin1String("bottom"), aiBottom)),
22642 bottomLeft(createAnchor(QLatin1String("bottomLeft"), aiBottomLeft)),
22143 bottomLeft(createAnchor(QLatin1String("bottomLeft"), aiBottomLeft)),
22643 left(createAnchor(QLatin1String("left"), aiLeft))
22144 left(createAnchor(QLatin1String("left"), aiLeft))
22644 {
22145 {
22645 position->setCoords(0, 0);
22146 position->setCoords(0, 0);
22646
22147
22647 setRotation(0);
22148 setRotation(0);
22648 setTextAlignment(Qt::AlignTop|Qt::AlignHCenter);
22149 setTextAlignment(Qt::AlignTop|Qt::AlignHCenter);
22649 setPositionAlignment(Qt::AlignCenter);
22150 setPositionAlignment(Qt::AlignCenter);
22650 setText(QLatin1String("text"));
22151 setText(QLatin1String("text"));
22651
22152
22652 setPen(Qt::NoPen);
22153 setPen(Qt::NoPen);
22653 setSelectedPen(Qt::NoPen);
22154 setSelectedPen(Qt::NoPen);
22654 setBrush(Qt::NoBrush);
22155 setBrush(Qt::NoBrush);
22655 setSelectedBrush(Qt::NoBrush);
22156 setSelectedBrush(Qt::NoBrush);
22656 setColor(Qt::black);
22157 setColor(Qt::black);
22657 setSelectedColor(Qt::blue);
22158 setSelectedColor(Qt::blue);
22658 }
22159 }
22659
22160
22660 QCPItemText::~QCPItemText()
22161 QCPItemText::~QCPItemText()
@@ -22666,7 +22167,7 QCPItemText::~QCPItemText()
22666 */
22167 */
22667 void QCPItemText::setColor(const QColor &color)
22168 void QCPItemText::setColor(const QColor &color)
22668 {
22169 {
22669 mColor = color;
22170 mColor = color;
22670 }
22171 }
22671
22172
22672 /*!
22173 /*!
@@ -22674,7 +22175,7 void QCPItemText::setColor(const QColor
22674 */
22175 */
22675 void QCPItemText::setSelectedColor(const QColor &color)
22176 void QCPItemText::setSelectedColor(const QColor &color)
22676 {
22177 {
22677 mSelectedColor = color;
22178 mSelectedColor = color;
22678 }
22179 }
22679
22180
22680 /*!
22181 /*!
@@ -22685,7 +22186,7 void QCPItemText::setSelectedColor(const
22685 */
22186 */
22686 void QCPItemText::setPen(const QPen &pen)
22187 void QCPItemText::setPen(const QPen &pen)
22687 {
22188 {
22688 mPen = pen;
22189 mPen = pen;
22689 }
22190 }
22690
22191
22691 /*!
22192 /*!
@@ -22696,7 +22197,7 void QCPItemText::setPen(const QPen &pen
22696 */
22197 */
22697 void QCPItemText::setSelectedPen(const QPen &pen)
22198 void QCPItemText::setSelectedPen(const QPen &pen)
22698 {
22199 {
22699 mSelectedPen = pen;
22200 mSelectedPen = pen;
22700 }
22201 }
22701
22202
22702 /*!
22203 /*!
@@ -22707,7 +22208,7 void QCPItemText::setSelectedPen(const Q
22707 */
22208 */
22708 void QCPItemText::setBrush(const QBrush &brush)
22209 void QCPItemText::setBrush(const QBrush &brush)
22709 {
22210 {
22710 mBrush = brush;
22211 mBrush = brush;
22711 }
22212 }
22712
22213
22713 /*!
22214 /*!
@@ -22718,7 +22219,7 void QCPItemText::setBrush(const QBrush
22718 */
22219 */
22719 void QCPItemText::setSelectedBrush(const QBrush &brush)
22220 void QCPItemText::setSelectedBrush(const QBrush &brush)
22720 {
22221 {
22721 mSelectedBrush = brush;
22222 mSelectedBrush = brush;
22722 }
22223 }
22723
22224
22724 /*!
22225 /*!
@@ -22728,7 +22229,7 void QCPItemText::setSelectedBrush(const
22728 */
22229 */
22729 void QCPItemText::setFont(const QFont &font)
22230 void QCPItemText::setFont(const QFont &font)
22730 {
22231 {
22731 mFont = font;
22232 mFont = font;
22732 }
22233 }
22733
22234
22734 /*!
22235 /*!
@@ -22738,7 +22239,7 void QCPItemText::setFont(const QFont &f
22738 */
22239 */
22739 void QCPItemText::setSelectedFont(const QFont &font)
22240 void QCPItemText::setSelectedFont(const QFont &font)
22740 {
22241 {
22741 mSelectedFont = font;
22242 mSelectedFont = font;
22742 }
22243 }
22743
22244
22744 /*!
22245 /*!
@@ -22749,7 +22250,7 void QCPItemText::setSelectedFont(const
22749 */
22250 */
22750 void QCPItemText::setText(const QString &text)
22251 void QCPItemText::setText(const QString &text)
22751 {
22252 {
22752 mText = text;
22253 mText = text;
22753 }
22254 }
22754
22255
22755 /*!
22256 /*!
@@ -22766,7 +22267,7 void QCPItemText::setText(const QString
22766 */
22267 */
22767 void QCPItemText::setPositionAlignment(Qt::Alignment alignment)
22268 void QCPItemText::setPositionAlignment(Qt::Alignment alignment)
22768 {
22269 {
22769 mPositionAlignment = alignment;
22270 mPositionAlignment = alignment;
22770 }
22271 }
22771
22272
22772 /*!
22273 /*!
@@ -22774,7 +22275,7 void QCPItemText::setPositionAlignment(Q
22774 */
22275 */
22775 void QCPItemText::setTextAlignment(Qt::Alignment alignment)
22276 void QCPItemText::setTextAlignment(Qt::Alignment alignment)
22776 {
22277 {
22777 mTextAlignment = alignment;
22278 mTextAlignment = alignment;
22778 }
22279 }
22779
22280
22780 /*!
22281 /*!
@@ -22783,7 +22284,7 void QCPItemText::setTextAlignment(Qt::A
22783 */
22284 */
22784 void QCPItemText::setRotation(double degrees)
22285 void QCPItemText::setRotation(double degrees)
22785 {
22286 {
22786 mRotation = degrees;
22287 mRotation = degrees;
22787 }
22288 }
22788
22289
22789 /*!
22290 /*!
@@ -22792,82 +22293,82 void QCPItemText::setRotation(double deg
22792 */
22293 */
22793 void QCPItemText::setPadding(const QMargins &padding)
22294 void QCPItemText::setPadding(const QMargins &padding)
22794 {
22295 {
22795 mPadding = padding;
22296 mPadding = padding;
22796 }
22297 }
22797
22298
22798 /* inherits documentation from base class */
22299 /* inherits documentation from base class */
22799 double QCPItemText::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
22300 double QCPItemText::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
22800 {
22301 {
22801 Q_UNUSED(details)
22302 Q_UNUSED(details)
22802 if (onlySelectable && !mSelectable)
22303 if (onlySelectable && !mSelectable)
22803 return -1;
22304 return -1;
22804
22305
22805 // The rect may be rotated, so we transform the actual clicked pos to the rotated
22306 // The rect may be rotated, so we transform the actual clicked pos to the rotated
22806 // coordinate system, so we can use the normal rectSelectTest function for non-rotated rects:
22307 // coordinate system, so we can use the normal rectSelectTest function for non-rotated rects:
22807 QPointF positionPixels(position->pixelPoint());
22308 QPointF positionPixels(position->pixelPoint());
22808 QTransform inputTransform;
22309 QTransform inputTransform;
22809 inputTransform.translate(positionPixels.x(), positionPixels.y());
22310 inputTransform.translate(positionPixels.x(), positionPixels.y());
22810 inputTransform.rotate(-mRotation);
22311 inputTransform.rotate(-mRotation);
22811 inputTransform.translate(-positionPixels.x(), -positionPixels.y());
22312 inputTransform.translate(-positionPixels.x(), -positionPixels.y());
22812 QPointF rotatedPos = inputTransform.map(pos);
22313 QPointF rotatedPos = inputTransform.map(pos);
22813 QFontMetrics fontMetrics(mFont);
22314 QFontMetrics fontMetrics(mFont);
22814 QRect textRect = fontMetrics.boundingRect(0, 0, 0, 0, Qt::TextDontClip|mTextAlignment, mText);
22315 QRect textRect = fontMetrics.boundingRect(0, 0, 0, 0, Qt::TextDontClip|mTextAlignment, mText);
22815 QRect textBoxRect = textRect.adjusted(-mPadding.left(), -mPadding.top(), mPadding.right(), mPadding.bottom());
22316 QRect textBoxRect = textRect.adjusted(-mPadding.left(), -mPadding.top(), mPadding.right(), mPadding.bottom());
22816 QPointF textPos = getTextDrawPoint(positionPixels, textBoxRect, mPositionAlignment);
22317 QPointF textPos = getTextDrawPoint(positionPixels, textBoxRect, mPositionAlignment);
22817 textBoxRect.moveTopLeft(textPos.toPoint());
22318 textBoxRect.moveTopLeft(textPos.toPoint());
22818
22319
22819 return rectSelectTest(textBoxRect, rotatedPos, true);
22320 return rectSelectTest(textBoxRect, rotatedPos, true);
22820 }
22321 }
22821
22322
22822 /* inherits documentation from base class */
22323 /* inherits documentation from base class */
22823 void QCPItemText::draw(QCPPainter *painter)
22324 void QCPItemText::draw(QCPPainter *painter)
22824 {
22325 {
22825 QPointF pos(position->pixelPoint());
22326 QPointF pos(position->pixelPoint());
22826 QTransform transform = painter->transform();
22327 QTransform transform = painter->transform();
22827 transform.translate(pos.x(), pos.y());
22328 transform.translate(pos.x(), pos.y());
22828 if (!qFuzzyIsNull(mRotation))
22329 if (!qFuzzyIsNull(mRotation))
22829 transform.rotate(mRotation);
22330 transform.rotate(mRotation);
22830 painter->setFont(mainFont());
22331 painter->setFont(mainFont());
22831 QRect textRect = painter->fontMetrics().boundingRect(0, 0, 0, 0, Qt::TextDontClip|mTextAlignment, mText);
22332 QRect textRect = painter->fontMetrics().boundingRect(0, 0, 0, 0, Qt::TextDontClip|mTextAlignment, mText);
22832 QRect textBoxRect = textRect.adjusted(-mPadding.left(), -mPadding.top(), mPadding.right(), mPadding.bottom());
22333 QRect textBoxRect = textRect.adjusted(-mPadding.left(), -mPadding.top(), mPadding.right(), mPadding.bottom());
22833 QPointF textPos = getTextDrawPoint(QPointF(0, 0), textBoxRect, mPositionAlignment); // 0, 0 because the transform does the translation
22334 QPointF textPos = getTextDrawPoint(QPointF(0, 0), textBoxRect, mPositionAlignment); // 0, 0 because the transform does the translation
22834 textRect.moveTopLeft(textPos.toPoint()+QPoint(mPadding.left(), mPadding.top()));
22335 textRect.moveTopLeft(textPos.toPoint()+QPoint(mPadding.left(), mPadding.top()));
22835 textBoxRect.moveTopLeft(textPos.toPoint());
22336 textBoxRect.moveTopLeft(textPos.toPoint());
22836 double clipPad = mainPen().widthF();
22337 double clipPad = mainPen().widthF();
22837 QRect boundingRect = textBoxRect.adjusted(-clipPad, -clipPad, clipPad, clipPad);
22338 QRect boundingRect = textBoxRect.adjusted(-clipPad, -clipPad, clipPad, clipPad);
22838 if (transform.mapRect(boundingRect).intersects(painter->transform().mapRect(clipRect())))
22339 if (transform.mapRect(boundingRect).intersects(painter->transform().mapRect(clipRect())))
22839 {
22340 {
22840 painter->setTransform(transform);
22341 painter->setTransform(transform);
22841 if ((mainBrush().style() != Qt::NoBrush && mainBrush().color().alpha() != 0) ||
22342 if ((mainBrush().style() != Qt::NoBrush && mainBrush().color().alpha() != 0) ||
22842 (mainPen().style() != Qt::NoPen && mainPen().color().alpha() != 0))
22343 (mainPen().style() != Qt::NoPen && mainPen().color().alpha() != 0))
22843 {
22344 {
22844 painter->setPen(mainPen());
22345 painter->setPen(mainPen());
22845 painter->setBrush(mainBrush());
22346 painter->setBrush(mainBrush());
22846 painter->drawRect(textBoxRect);
22347 painter->drawRect(textBoxRect);
22847 }
22348 }
22848 painter->setBrush(Qt::NoBrush);
22349 painter->setBrush(Qt::NoBrush);
22849 painter->setPen(QPen(mainColor()));
22350 painter->setPen(QPen(mainColor()));
22850 painter->drawText(textRect, Qt::TextDontClip|mTextAlignment, mText);
22351 painter->drawText(textRect, Qt::TextDontClip|mTextAlignment, mText);
22851 }
22352 }
22852 }
22353 }
22853
22354
22854 /* inherits documentation from base class */
22355 /* inherits documentation from base class */
22855 QPointF QCPItemText::anchorPixelPoint(int anchorId) const
22356 QPointF QCPItemText::anchorPixelPoint(int anchorId) const
22856 {
22357 {
22857 // get actual rect points (pretty much copied from draw function):
22358 // get actual rect points (pretty much copied from draw function):
22858 QPointF pos(position->pixelPoint());
22359 QPointF pos(position->pixelPoint());
22859 QTransform transform;
22360 QTransform transform;
22860 transform.translate(pos.x(), pos.y());
22361 transform.translate(pos.x(), pos.y());
22861 if (!qFuzzyIsNull(mRotation))
22362 if (!qFuzzyIsNull(mRotation))
22862 transform.rotate(mRotation);
22363 transform.rotate(mRotation);
22863 QFontMetrics fontMetrics(mainFont());
22364 QFontMetrics fontMetrics(mainFont());
22864 QRect textRect = fontMetrics.boundingRect(0, 0, 0, 0, Qt::TextDontClip|mTextAlignment, mText);
22365 QRect textRect = fontMetrics.boundingRect(0, 0, 0, 0, Qt::TextDontClip|mTextAlignment, mText);
22865 QRectF textBoxRect = textRect.adjusted(-mPadding.left(), -mPadding.top(), mPadding.right(), mPadding.bottom());
22366 QRectF textBoxRect = textRect.adjusted(-mPadding.left(), -mPadding.top(), mPadding.right(), mPadding.bottom());
22866 QPointF textPos = getTextDrawPoint(QPointF(0, 0), textBoxRect, mPositionAlignment); // 0, 0 because the transform does the translation
22367 QPointF textPos = getTextDrawPoint(QPointF(0, 0), textBoxRect, mPositionAlignment); // 0, 0 because the transform does the translation
22867 textBoxRect.moveTopLeft(textPos.toPoint());
22368 textBoxRect.moveTopLeft(textPos.toPoint());
22868 QPolygonF rectPoly = transform.map(QPolygonF(textBoxRect));
22369 QPolygonF rectPoly = transform.map(QPolygonF(textBoxRect));
22869
22370
22870 switch (anchorId)
22371 switch (anchorId)
22871 {
22372 {
22872 case aiTopLeft: return rectPoly.at(0);
22373 case aiTopLeft: return rectPoly.at(0);
22873 case aiTop: return (rectPoly.at(0)+rectPoly.at(1))*0.5;
22374 case aiTop: return (rectPoly.at(0)+rectPoly.at(1))*0.5;
@@ -22878,9 +22379,9 QPointF QCPItemText::anchorPixelPoint(in
22878 case aiBottomLeft: return rectPoly.at(3);
22379 case aiBottomLeft: return rectPoly.at(3);
22879 case aiLeft: return (rectPoly.at(3)+rectPoly.at(0))*0.5;
22380 case aiLeft: return (rectPoly.at(3)+rectPoly.at(0))*0.5;
22880 }
22381 }
22881
22382
22882 qDebug() << Q_FUNC_INFO << "invalid anchorId" << anchorId;
22383 qDebug() << Q_FUNC_INFO << "invalid anchorId" << anchorId;
22883 return QPointF();
22384 return QPointF();
22884 }
22385 }
22885
22386
22886 /*! \internal
22387 /*! \internal
@@ -22895,19 +22396,19 QPointF QCPItemText::anchorPixelPoint(in
22895 */
22396 */
22896 QPointF QCPItemText::getTextDrawPoint(const QPointF &pos, const QRectF &rect, Qt::Alignment positionAlignment) const
22397 QPointF QCPItemText::getTextDrawPoint(const QPointF &pos, const QRectF &rect, Qt::Alignment positionAlignment) const
22897 {
22398 {
22898 if (positionAlignment == 0 || positionAlignment == (Qt::AlignLeft|Qt::AlignTop))
22399 if (positionAlignment == 0 || positionAlignment == (Qt::AlignLeft|Qt::AlignTop))
22899 return pos;
22400 return pos;
22900
22401
22901 QPointF result = pos; // start at top left
22402 QPointF result = pos; // start at top left
22902 if (positionAlignment.testFlag(Qt::AlignHCenter))
22403 if (positionAlignment.testFlag(Qt::AlignHCenter))
22903 result.rx() -= rect.width()/2.0;
22404 result.rx() -= rect.width()/2.0;
22904 else if (positionAlignment.testFlag(Qt::AlignRight))
22405 else if (positionAlignment.testFlag(Qt::AlignRight))
22905 result.rx() -= rect.width();
22406 result.rx() -= rect.width();
22906 if (positionAlignment.testFlag(Qt::AlignVCenter))
22407 if (positionAlignment.testFlag(Qt::AlignVCenter))
22907 result.ry() -= rect.height()/2.0;
22408 result.ry() -= rect.height()/2.0;
22908 else if (positionAlignment.testFlag(Qt::AlignBottom))
22409 else if (positionAlignment.testFlag(Qt::AlignBottom))
22909 result.ry() -= rect.height();
22410 result.ry() -= rect.height();
22910 return result;
22411 return result;
22911 }
22412 }
22912
22413
22913 /*! \internal
22414 /*! \internal
@@ -22917,7 +22418,7 QPointF QCPItemText::getTextDrawPoint(co
22917 */
22418 */
22918 QFont QCPItemText::mainFont() const
22419 QFont QCPItemText::mainFont() const
22919 {
22420 {
22920 return mSelected ? mSelectedFont : mFont;
22421 return mSelected ? mSelectedFont : mFont;
22921 }
22422 }
22922
22423
22923 /*! \internal
22424 /*! \internal
@@ -22927,7 +22428,7 QFont QCPItemText::mainFont() const
22927 */
22428 */
22928 QColor QCPItemText::mainColor() const
22429 QColor QCPItemText::mainColor() const
22929 {
22430 {
22930 return mSelected ? mSelectedColor : mColor;
22431 return mSelected ? mSelectedColor : mColor;
22931 }
22432 }
22932
22433
22933 /*! \internal
22434 /*! \internal
@@ -22937,7 +22438,7 QColor QCPItemText::mainColor() const
22937 */
22438 */
22938 QPen QCPItemText::mainPen() const
22439 QPen QCPItemText::mainPen() const
22939 {
22440 {
22940 return mSelected ? mSelectedPen : mPen;
22441 return mSelected ? mSelectedPen : mPen;
22941 }
22442 }
22942
22443
22943 /*! \internal
22444 /*! \internal
@@ -22947,7 +22448,7 QPen QCPItemText::mainPen() const
22947 */
22448 */
22948 QBrush QCPItemText::mainBrush() const
22449 QBrush QCPItemText::mainBrush() const
22949 {
22450 {
22950 return mSelected ? mSelectedBrush : mBrush;
22451 return mSelected ? mSelectedBrush : mBrush;
22951 }
22452 }
22952
22453
22953
22454
@@ -22969,26 +22470,26 QBrush QCPItemText::mainBrush() const
22969 The constructed item can be added to the plot with QCustomPlot::addItem.
22470 The constructed item can be added to the plot with QCustomPlot::addItem.
22970 */
22471 */
22971 QCPItemEllipse::QCPItemEllipse(QCustomPlot *parentPlot) :
22472 QCPItemEllipse::QCPItemEllipse(QCustomPlot *parentPlot) :
22972 QCPAbstractItem(parentPlot),
22473 QCPAbstractItem(parentPlot),
22973 topLeft(createPosition(QLatin1String("topLeft"))),
22474 topLeft(createPosition(QLatin1String("topLeft"))),
22974 bottomRight(createPosition(QLatin1String("bottomRight"))),
22475 bottomRight(createPosition(QLatin1String("bottomRight"))),
22975 topLeftRim(createAnchor(QLatin1String("topLeftRim"), aiTopLeftRim)),
22476 topLeftRim(createAnchor(QLatin1String("topLeftRim"), aiTopLeftRim)),
22976 top(createAnchor(QLatin1String("top"), aiTop)),
22477 top(createAnchor(QLatin1String("top"), aiTop)),
22977 topRightRim(createAnchor(QLatin1String("topRightRim"), aiTopRightRim)),
22478 topRightRim(createAnchor(QLatin1String("topRightRim"), aiTopRightRim)),
22978 right(createAnchor(QLatin1String("right"), aiRight)),
22479 right(createAnchor(QLatin1String("right"), aiRight)),
22979 bottomRightRim(createAnchor(QLatin1String("bottomRightRim"), aiBottomRightRim)),
22480 bottomRightRim(createAnchor(QLatin1String("bottomRightRim"), aiBottomRightRim)),
22980 bottom(createAnchor(QLatin1String("bottom"), aiBottom)),
22481 bottom(createAnchor(QLatin1String("bottom"), aiBottom)),
22981 bottomLeftRim(createAnchor(QLatin1String("bottomLeftRim"), aiBottomLeftRim)),
22482 bottomLeftRim(createAnchor(QLatin1String("bottomLeftRim"), aiBottomLeftRim)),
22982 left(createAnchor(QLatin1String("left"), aiLeft)),
22483 left(createAnchor(QLatin1String("left"), aiLeft)),
22983 center(createAnchor(QLatin1String("center"), aiCenter))
22484 center(createAnchor(QLatin1String("center"), aiCenter))
22984 {
22485 {
22985 topLeft->setCoords(0, 1);
22486 topLeft->setCoords(0, 1);
22986 bottomRight->setCoords(1, 0);
22487 bottomRight->setCoords(1, 0);
22987
22488
22988 setPen(QPen(Qt::black));
22489 setPen(QPen(Qt::black));
22989 setSelectedPen(QPen(Qt::blue, 2));
22490 setSelectedPen(QPen(Qt::blue, 2));
22990 setBrush(Qt::NoBrush);
22491 setBrush(Qt::NoBrush);
22991 setSelectedBrush(Qt::NoBrush);
22492 setSelectedBrush(Qt::NoBrush);
22992 }
22493 }
22993
22494
22994 QCPItemEllipse::~QCPItemEllipse()
22495 QCPItemEllipse::~QCPItemEllipse()
@@ -23002,7 +22503,7 QCPItemEllipse::~QCPItemEllipse()
23002 */
22503 */
23003 void QCPItemEllipse::setPen(const QPen &pen)
22504 void QCPItemEllipse::setPen(const QPen &pen)
23004 {
22505 {
23005 mPen = pen;
22506 mPen = pen;
23006 }
22507 }
23007
22508
23008 /*!
22509 /*!
@@ -23012,7 +22513,7 void QCPItemEllipse::setPen(const QPen &
23012 */
22513 */
23013 void QCPItemEllipse::setSelectedPen(const QPen &pen)
22514 void QCPItemEllipse::setSelectedPen(const QPen &pen)
23014 {
22515 {
23015 mSelectedPen = pen;
22516 mSelectedPen = pen;
23016 }
22517 }
23017
22518
23018 /*!
22519 /*!
@@ -23023,7 +22524,7 void QCPItemEllipse::setSelectedPen(cons
23023 */
22524 */
23024 void QCPItemEllipse::setBrush(const QBrush &brush)
22525 void QCPItemEllipse::setBrush(const QBrush &brush)
23025 {
22526 {
23026 mBrush = brush;
22527 mBrush = brush;
23027 }
22528 }
23028
22529
23029 /*!
22530 /*!
@@ -23034,61 +22535,61 void QCPItemEllipse::setBrush(const QBru
23034 */
22535 */
23035 void QCPItemEllipse::setSelectedBrush(const QBrush &brush)
22536 void QCPItemEllipse::setSelectedBrush(const QBrush &brush)
23036 {
22537 {
23037 mSelectedBrush = brush;
22538 mSelectedBrush = brush;
23038 }
22539 }
23039
22540
23040 /* inherits documentation from base class */
22541 /* inherits documentation from base class */
23041 double QCPItemEllipse::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
22542 double QCPItemEllipse::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
23042 {
22543 {
23043 Q_UNUSED(details)
22544 Q_UNUSED(details)
23044 if (onlySelectable && !mSelectable)
22545 if (onlySelectable && !mSelectable)
23045 return -1;
22546 return -1;
23046
22547
23047 double result = -1;
22548 double result = -1;
23048 QPointF p1 = topLeft->pixelPoint();
22549 QPointF p1 = topLeft->pixelPoint();
23049 QPointF p2 = bottomRight->pixelPoint();
22550 QPointF p2 = bottomRight->pixelPoint();
23050 QPointF center((p1+p2)/2.0);
22551 QPointF center((p1+p2)/2.0);
23051 double a = qAbs(p1.x()-p2.x())/2.0;
22552 double a = qAbs(p1.x()-p2.x())/2.0;
23052 double b = qAbs(p1.y()-p2.y())/2.0;
22553 double b = qAbs(p1.y()-p2.y())/2.0;
23053 double x = pos.x()-center.x();
22554 double x = pos.x()-center.x();
23054 double y = pos.y()-center.y();
22555 double y = pos.y()-center.y();
23055
22556
23056 // distance to border:
22557 // distance to border:
23057 double c = 1.0/qSqrt(x*x/(a*a)+y*y/(b*b));
22558 double c = 1.0/qSqrt(x*x/(a*a)+y*y/(b*b));
23058 result = qAbs(c-1)*qSqrt(x*x+y*y);
22559 result = qAbs(c-1)*qSqrt(x*x+y*y);
23059 // filled ellipse, allow click inside to count as hit:
22560 // filled ellipse, allow click inside to count as hit:
23060 if (result > mParentPlot->selectionTolerance()*0.99 && mBrush.style() != Qt::NoBrush && mBrush.color().alpha() != 0)
22561 if (result > mParentPlot->selectionTolerance()*0.99 && mBrush.style() != Qt::NoBrush && mBrush.color().alpha() != 0)
23061 {
22562 {
23062 if (x*x/(a*a) + y*y/(b*b) <= 1)
22563 if (x*x/(a*a) + y*y/(b*b) <= 1)
23063 result = mParentPlot->selectionTolerance()*0.99;
22564 result = mParentPlot->selectionTolerance()*0.99;
23064 }
22565 }
23065 return result;
22566 return result;
23066 }
22567 }
23067
22568
23068 /* inherits documentation from base class */
22569 /* inherits documentation from base class */
23069 void QCPItemEllipse::draw(QCPPainter *painter)
22570 void QCPItemEllipse::draw(QCPPainter *painter)
23070 {
22571 {
23071 QPointF p1 = topLeft->pixelPoint();
22572 QPointF p1 = topLeft->pixelPoint();
23072 QPointF p2 = bottomRight->pixelPoint();
22573 QPointF p2 = bottomRight->pixelPoint();
23073 if (p1.toPoint() == p2.toPoint())
22574 if (p1.toPoint() == p2.toPoint())
23074 return;
22575 return;
23075 QRectF ellipseRect = QRectF(p1, p2).normalized();
22576 QRectF ellipseRect = QRectF(p1, p2).normalized();
23076 QRect clip = clipRect().adjusted(-mainPen().widthF(), -mainPen().widthF(), mainPen().widthF(), mainPen().widthF());
22577 QRect clip = clipRect().adjusted(-mainPen().widthF(), -mainPen().widthF(), mainPen().widthF(), mainPen().widthF());
23077 if (ellipseRect.intersects(clip)) // only draw if bounding rect of ellipse is visible in cliprect
22578 if (ellipseRect.intersects(clip)) // only draw if bounding rect of ellipse is visible in cliprect
23078 {
22579 {
23079 painter->setPen(mainPen());
22580 painter->setPen(mainPen());
23080 painter->setBrush(mainBrush());
22581 painter->setBrush(mainBrush());
23081 #ifdef __EXCEPTIONS
22582 #ifdef __EXCEPTIONS
23082 try // drawEllipse sometimes throws exceptions if ellipse is too big
22583 try // drawEllipse sometimes throws exceptions if ellipse is too big
23083 {
22584 {
23084 #endif
22585 #endif
23085 painter->drawEllipse(ellipseRect);
22586 painter->drawEllipse(ellipseRect);
23086 #ifdef __EXCEPTIONS
22587 #ifdef __EXCEPTIONS
23087 } catch (...)
22588 } catch (...)
23088 {
22589 {
23089 qDebug() << Q_FUNC_INFO << "Item too large for memory, setting invisible";
22590 qDebug() << Q_FUNC_INFO << "Item too large for memory, setting invisible";
23090 setVisible(false);
22591 setVisible(false);
23091 }
22592 }
23092 #endif
22593 #endif
23093 }
22594 }
23094 }
22595 }
@@ -23096,8 +22597,8 void QCPItemEllipse::draw(QCPPainter *pa
23096 /* inherits documentation from base class */
22597 /* inherits documentation from base class */
23097 QPointF QCPItemEllipse::anchorPixelPoint(int anchorId) const
22598 QPointF QCPItemEllipse::anchorPixelPoint(int anchorId) const
23098 {
22599 {
23099 QRectF rect = QRectF(topLeft->pixelPoint(), bottomRight->pixelPoint());
22600 QRectF rect = QRectF(topLeft->pixelPoint(), bottomRight->pixelPoint());
23100 switch (anchorId)
22601 switch (anchorId)
23101 {
22602 {
23102 case aiTopLeftRim: return rect.center()+(rect.topLeft()-rect.center())*1/qSqrt(2);
22603 case aiTopLeftRim: return rect.center()+(rect.topLeft()-rect.center())*1/qSqrt(2);
23103 case aiTop: return (rect.topLeft()+rect.topRight())*0.5;
22604 case aiTop: return (rect.topLeft()+rect.topRight())*0.5;
@@ -23109,9 +22610,9 QPointF QCPItemEllipse::anchorPixelPoint
23109 case aiLeft: return (rect.topLeft()+rect.bottomLeft())*0.5;
22610 case aiLeft: return (rect.topLeft()+rect.bottomLeft())*0.5;
23110 case aiCenter: return (rect.topLeft()+rect.bottomRight())*0.5;
22611 case aiCenter: return (rect.topLeft()+rect.bottomRight())*0.5;
23111 }
22612 }
23112
22613
23113 qDebug() << Q_FUNC_INFO << "invalid anchorId" << anchorId;
22614 qDebug() << Q_FUNC_INFO << "invalid anchorId" << anchorId;
23114 return QPointF();
22615 return QPointF();
23115 }
22616 }
23116
22617
23117 /*! \internal
22618 /*! \internal
@@ -23121,7 +22622,7 QPointF QCPItemEllipse::anchorPixelPoint
23121 */
22622 */
23122 QPen QCPItemEllipse::mainPen() const
22623 QPen QCPItemEllipse::mainPen() const
23123 {
22624 {
23124 return mSelected ? mSelectedPen : mPen;
22625 return mSelected ? mSelectedPen : mPen;
23125 }
22626 }
23126
22627
23127 /*! \internal
22628 /*! \internal
@@ -23131,7 +22632,7 QPen QCPItemEllipse::mainPen() const
23131 */
22632 */
23132 QBrush QCPItemEllipse::mainBrush() const
22633 QBrush QCPItemEllipse::mainBrush() const
23133 {
22634 {
23134 return mSelected ? mSelectedBrush : mBrush;
22635 return mSelected ? mSelectedBrush : mBrush;
23135 }
22636 }
23136
22637
23137
22638
@@ -23159,22 +22660,22 QBrush QCPItemEllipse::mainBrush() const
23159 The constructed item can be added to the plot with QCustomPlot::addItem.
22660 The constructed item can be added to the plot with QCustomPlot::addItem.
23160 */
22661 */
23161 QCPItemPixmap::QCPItemPixmap(QCustomPlot *parentPlot) :
22662 QCPItemPixmap::QCPItemPixmap(QCustomPlot *parentPlot) :
23162 QCPAbstractItem(parentPlot),
22663 QCPAbstractItem(parentPlot),
23163 topLeft(createPosition(QLatin1String("topLeft"))),
22664 topLeft(createPosition(QLatin1String("topLeft"))),
23164 bottomRight(createPosition(QLatin1String("bottomRight"))),
22665 bottomRight(createPosition(QLatin1String("bottomRight"))),
23165 top(createAnchor(QLatin1String("top"), aiTop)),
22666 top(createAnchor(QLatin1String("top"), aiTop)),
23166 topRight(createAnchor(QLatin1String("topRight"), aiTopRight)),
22667 topRight(createAnchor(QLatin1String("topRight"), aiTopRight)),
23167 right(createAnchor(QLatin1String("right"), aiRight)),
22668 right(createAnchor(QLatin1String("right"), aiRight)),
23168 bottom(createAnchor(QLatin1String("bottom"), aiBottom)),
22669 bottom(createAnchor(QLatin1String("bottom"), aiBottom)),
23169 bottomLeft(createAnchor(QLatin1String("bottomLeft"), aiBottomLeft)),
22670 bottomLeft(createAnchor(QLatin1String("bottomLeft"), aiBottomLeft)),
23170 left(createAnchor(QLatin1String("left"), aiLeft))
22671 left(createAnchor(QLatin1String("left"), aiLeft))
23171 {
22672 {
23172 topLeft->setCoords(0, 1);
22673 topLeft->setCoords(0, 1);
23173 bottomRight->setCoords(1, 0);
22674 bottomRight->setCoords(1, 0);
23174
22675
23175 setPen(Qt::NoPen);
22676 setPen(Qt::NoPen);
23176 setSelectedPen(QPen(Qt::blue));
22677 setSelectedPen(QPen(Qt::blue));
23177 setScaled(false, Qt::KeepAspectRatio, Qt::SmoothTransformation);
22678 setScaled(false, Qt::KeepAspectRatio, Qt::SmoothTransformation);
23178 }
22679 }
23179
22680
23180 QCPItemPixmap::~QCPItemPixmap()
22681 QCPItemPixmap::~QCPItemPixmap()
@@ -23186,9 +22687,9 QCPItemPixmap::~QCPItemPixmap()
23186 */
22687 */
23187 void QCPItemPixmap::setPixmap(const QPixmap &pixmap)
22688 void QCPItemPixmap::setPixmap(const QPixmap &pixmap)
23188 {
22689 {
23189 mPixmap = pixmap;
22690 mPixmap = pixmap;
23190 if (mPixmap.isNull())
22691 if (mPixmap.isNull())
23191 qDebug() << Q_FUNC_INFO << "pixmap is null";
22692 qDebug() << Q_FUNC_INFO << "pixmap is null";
23192 }
22693 }
23193
22694
23194 /*!
22695 /*!
@@ -23197,10 +22698,10 void QCPItemPixmap::setPixmap(const QPix
23197 */
22698 */
23198 void QCPItemPixmap::setScaled(bool scaled, Qt::AspectRatioMode aspectRatioMode, Qt::TransformationMode transformationMode)
22699 void QCPItemPixmap::setScaled(bool scaled, Qt::AspectRatioMode aspectRatioMode, Qt::TransformationMode transformationMode)
23199 {
22700 {
23200 mScaled = scaled;
22701 mScaled = scaled;
23201 mAspectRatioMode = aspectRatioMode;
22702 mAspectRatioMode = aspectRatioMode;
23202 mTransformationMode = transformationMode;
22703 mTransformationMode = transformationMode;
23203 updateScaledPixmap();
22704 updateScaledPixmap();
23204 }
22705 }
23205
22706
23206 /*!
22707 /*!
@@ -23210,7 +22711,7 void QCPItemPixmap::setScaled(bool scale
23210 */
22711 */
23211 void QCPItemPixmap::setPen(const QPen &pen)
22712 void QCPItemPixmap::setPen(const QPen &pen)
23212 {
22713 {
23213 mPen = pen;
22714 mPen = pen;
23214 }
22715 }
23215
22716
23216 /*!
22717 /*!
@@ -23220,37 +22721,37 void QCPItemPixmap::setPen(const QPen &p
23220 */
22721 */
23221 void QCPItemPixmap::setSelectedPen(const QPen &pen)
22722 void QCPItemPixmap::setSelectedPen(const QPen &pen)
23222 {
22723 {
23223 mSelectedPen = pen;
22724 mSelectedPen = pen;
23224 }
22725 }
23225
22726
23226 /* inherits documentation from base class */
22727 /* inherits documentation from base class */
23227 double QCPItemPixmap::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
22728 double QCPItemPixmap::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
23228 {
22729 {
23229 Q_UNUSED(details)
22730 Q_UNUSED(details)
23230 if (onlySelectable && !mSelectable)
22731 if (onlySelectable && !mSelectable)
23231 return -1;
22732 return -1;
23232
22733
23233 return rectSelectTest(getFinalRect(), pos, true);
22734 return rectSelectTest(getFinalRect(), pos, true);
23234 }
22735 }
23235
22736
23236 /* inherits documentation from base class */
22737 /* inherits documentation from base class */
23237 void QCPItemPixmap::draw(QCPPainter *painter)
22738 void QCPItemPixmap::draw(QCPPainter *painter)
23238 {
22739 {
23239 bool flipHorz = false;
22740 bool flipHorz = false;
23240 bool flipVert = false;
22741 bool flipVert = false;
23241 QRect rect = getFinalRect(&flipHorz, &flipVert);
22742 QRect rect = getFinalRect(&flipHorz, &flipVert);
23242 double clipPad = mainPen().style() == Qt::NoPen ? 0 : mainPen().widthF();
22743 double clipPad = mainPen().style() == Qt::NoPen ? 0 : mainPen().widthF();
23243 QRect boundingRect = rect.adjusted(-clipPad, -clipPad, clipPad, clipPad);
22744 QRect boundingRect = rect.adjusted(-clipPad, -clipPad, clipPad, clipPad);
23244 if (boundingRect.intersects(clipRect()))
22745 if (boundingRect.intersects(clipRect()))
23245 {
22746 {
23246 updateScaledPixmap(rect, flipHorz, flipVert);
22747 updateScaledPixmap(rect, flipHorz, flipVert);
23247 painter->drawPixmap(rect.topLeft(), mScaled ? mScaledPixmap : mPixmap);
22748 painter->drawPixmap(rect.topLeft(), mScaled ? mScaledPixmap : mPixmap);
23248 QPen pen = mainPen();
22749 QPen pen = mainPen();
23249 if (pen.style() != Qt::NoPen)
22750 if (pen.style() != Qt::NoPen)
23250 {
22751 {
23251 painter->setPen(pen);
22752 painter->setPen(pen);
23252 painter->setBrush(Qt::NoBrush);
22753 painter->setBrush(Qt::NoBrush);
23253 painter->drawRect(rect);
22754 painter->drawRect(rect);
23254 }
22755 }
23255 }
22756 }
23256 }
22757 }
@@ -23258,17 +22759,17 void QCPItemPixmap::draw(QCPPainter *pai
23258 /* inherits documentation from base class */
22759 /* inherits documentation from base class */
23259 QPointF QCPItemPixmap::anchorPixelPoint(int anchorId) const
22760 QPointF QCPItemPixmap::anchorPixelPoint(int anchorId) const
23260 {
22761 {
23261 bool flipHorz;
22762 bool flipHorz;
23262 bool flipVert;
22763 bool flipVert;
23263 QRect rect = getFinalRect(&flipHorz, &flipVert);
22764 QRect rect = getFinalRect(&flipHorz, &flipVert);
23264 // we actually want denormal rects (negative width/height) here, so restore
22765 // we actually want denormal rects (negative width/height) here, so restore
23265 // the flipped state:
22766 // the flipped state:
23266 if (flipHorz)
22767 if (flipHorz)
23267 rect.adjust(rect.width(), 0, -rect.width(), 0);
22768 rect.adjust(rect.width(), 0, -rect.width(), 0);
23268 if (flipVert)
22769 if (flipVert)
23269 rect.adjust(0, rect.height(), 0, -rect.height());
22770 rect.adjust(0, rect.height(), 0, -rect.height());
23270
22771
23271 switch (anchorId)
22772 switch (anchorId)
23272 {
22773 {
23273 case aiTop: return (rect.topLeft()+rect.topRight())*0.5;
22774 case aiTop: return (rect.topLeft()+rect.topRight())*0.5;
23274 case aiTopRight: return rect.topRight();
22775 case aiTopRight: return rect.topRight();
@@ -23277,9 +22778,9 QPointF QCPItemPixmap::anchorPixelPoint(
23277 case aiBottomLeft: return rect.bottomLeft();
22778 case aiBottomLeft: return rect.bottomLeft();
23278 case aiLeft: return (rect.topLeft()+rect.bottomLeft())*0.5;;
22779 case aiLeft: return (rect.topLeft()+rect.bottomLeft())*0.5;;
23279 }
22780 }
23280
22781
23281 qDebug() << Q_FUNC_INFO << "invalid anchorId" << anchorId;
22782 qDebug() << Q_FUNC_INFO << "invalid anchorId" << anchorId;
23282 return QPointF();
22783 return QPointF();
23283 }
22784 }
23284
22785
23285 /*! \internal
22786 /*! \internal
@@ -23297,21 +22798,21 QPointF QCPItemPixmap::anchorPixelPoint(
23297 */
22798 */
23298 void QCPItemPixmap::updateScaledPixmap(QRect finalRect, bool flipHorz, bool flipVert)
22799 void QCPItemPixmap::updateScaledPixmap(QRect finalRect, bool flipHorz, bool flipVert)
23299 {
22800 {
23300 if (mPixmap.isNull())
22801 if (mPixmap.isNull())
23301 return;
22802 return;
23302
22803
23303 if (mScaled)
22804 if (mScaled)
23304 {
22805 {
23305 if (finalRect.isNull())
22806 if (finalRect.isNull())
23306 finalRect = getFinalRect(&flipHorz, &flipVert);
22807 finalRect = getFinalRect(&flipHorz, &flipVert);
23307 if (finalRect.size() != mScaledPixmap.size())
22808 if (finalRect.size() != mScaledPixmap.size())
23308 {
22809 {
23309 mScaledPixmap = mPixmap.scaled(finalRect.size(), mAspectRatioMode, mTransformationMode);
22810 mScaledPixmap = mPixmap.scaled(finalRect.size(), mAspectRatioMode, mTransformationMode);
23310 if (flipHorz || flipVert)
22811 if (flipHorz || flipVert)
23311 mScaledPixmap = QPixmap::fromImage(mScaledPixmap.toImage().mirrored(flipHorz, flipVert));
22812 mScaledPixmap = QPixmap::fromImage(mScaledPixmap.toImage().mirrored(flipHorz, flipVert));
23312 }
22813 }
23313 } else if (!mScaledPixmap.isNull())
22814 } else if (!mScaledPixmap.isNull())
23314 mScaledPixmap = QPixmap();
22815 mScaledPixmap = QPixmap();
23315 }
22816 }
23316
22817
23317 /*! \internal
22818 /*! \internal
@@ -23330,41 +22831,41 void QCPItemPixmap::updateScaledPixmap(Q
23330 */
22831 */
23331 QRect QCPItemPixmap::getFinalRect(bool *flippedHorz, bool *flippedVert) const
22832 QRect QCPItemPixmap::getFinalRect(bool *flippedHorz, bool *flippedVert) const
23332 {
22833 {
23333 QRect result;
22834 QRect result;
23334 bool flipHorz = false;
22835 bool flipHorz = false;
23335 bool flipVert = false;
22836 bool flipVert = false;
23336 QPoint p1 = topLeft->pixelPoint().toPoint();
22837 QPoint p1 = topLeft->pixelPoint().toPoint();
23337 QPoint p2 = bottomRight->pixelPoint().toPoint();
22838 QPoint p2 = bottomRight->pixelPoint().toPoint();
23338 if (p1 == p2)
22839 if (p1 == p2)
23339 return QRect(p1, QSize(0, 0));
22840 return QRect(p1, QSize(0, 0));
23340 if (mScaled)
22841 if (mScaled)
23341 {
22842 {
23342 QSize newSize = QSize(p2.x()-p1.x(), p2.y()-p1.y());
22843 QSize newSize = QSize(p2.x()-p1.x(), p2.y()-p1.y());
23343 QPoint topLeft = p1;
22844 QPoint topLeft = p1;
23344 if (newSize.width() < 0)
22845 if (newSize.width() < 0)
23345 {
22846 {
23346 flipHorz = true;
22847 flipHorz = true;
23347 newSize.rwidth() *= -1;
22848 newSize.rwidth() *= -1;
23348 topLeft.setX(p2.x());
22849 topLeft.setX(p2.x());
23349 }
22850 }
23350 if (newSize.height() < 0)
22851 if (newSize.height() < 0)
23351 {
22852 {
23352 flipVert = true;
22853 flipVert = true;
23353 newSize.rheight() *= -1;
22854 newSize.rheight() *= -1;
23354 topLeft.setY(p2.y());
22855 topLeft.setY(p2.y());
23355 }
22856 }
23356 QSize scaledSize = mPixmap.size();
22857 QSize scaledSize = mPixmap.size();
23357 scaledSize.scale(newSize, mAspectRatioMode);
22858 scaledSize.scale(newSize, mAspectRatioMode);
23358 result = QRect(topLeft, scaledSize);
22859 result = QRect(topLeft, scaledSize);
23359 } else
22860 } else
23360 {
22861 {
23361 result = QRect(p1, mPixmap.size());
22862 result = QRect(p1, mPixmap.size());
23362 }
22863 }
23363 if (flippedHorz)
22864 if (flippedHorz)
23364 *flippedHorz = flipHorz;
22865 *flippedHorz = flipHorz;
23365 if (flippedVert)
22866 if (flippedVert)
23366 *flippedVert = flipVert;
22867 *flippedVert = flipVert;
23367 return result;
22868 return result;
23368 }
22869 }
23369
22870
23370 /*! \internal
22871 /*! \internal
@@ -23374,7 +22875,7 QRect QCPItemPixmap::getFinalRect(bool *
23374 */
22875 */
23375 QPen QCPItemPixmap::mainPen() const
22876 QPen QCPItemPixmap::mainPen() const
23376 {
22877 {
23377 return mSelected ? mSelectedPen : mPen;
22878 return mSelected ? mSelectedPen : mPen;
23378 }
22879 }
23379
22880
23380
22881
@@ -23418,20 +22919,20 QPen QCPItemPixmap::mainPen() const
23418 The constructed item can be added to the plot with QCustomPlot::addItem.
22919 The constructed item can be added to the plot with QCustomPlot::addItem.
23419 */
22920 */
23420 QCPItemTracer::QCPItemTracer(QCustomPlot *parentPlot) :
22921 QCPItemTracer::QCPItemTracer(QCustomPlot *parentPlot) :
23421 QCPAbstractItem(parentPlot),
22922 QCPAbstractItem(parentPlot),
23422 position(createPosition(QLatin1String("position"))),
22923 position(createPosition(QLatin1String("position"))),
23423 mGraph(0)
22924 mGraph(0)
23424 {
22925 {
23425 position->setCoords(0, 0);
22926 position->setCoords(0, 0);
23426
22927
23427 setBrush(Qt::NoBrush);
22928 setBrush(Qt::NoBrush);
23428 setSelectedBrush(Qt::NoBrush);
22929 setSelectedBrush(Qt::NoBrush);
23429 setPen(QPen(Qt::black));
22930 setPen(QPen(Qt::black));
23430 setSelectedPen(QPen(Qt::blue, 2));
22931 setSelectedPen(QPen(Qt::blue, 2));
23431 setStyle(tsCrosshair);
22932 setStyle(tsCrosshair);
23432 setSize(6);
22933 setSize(6);
23433 setInterpolating(false);
22934 setInterpolating(false);
23434 setGraphKey(0);
22935 setGraphKey(0);
23435 }
22936 }
23436
22937
23437 QCPItemTracer::~QCPItemTracer()
22938 QCPItemTracer::~QCPItemTracer()
@@ -23445,7 +22946,7 QCPItemTracer::~QCPItemTracer()
23445 */
22946 */
23446 void QCPItemTracer::setPen(const QPen &pen)
22947 void QCPItemTracer::setPen(const QPen &pen)
23447 {
22948 {
23448 mPen = pen;
22949 mPen = pen;
23449 }
22950 }
23450
22951
23451 /*!
22952 /*!
@@ -23455,7 +22956,7 void QCPItemTracer::setPen(const QPen &p
23455 */
22956 */
23456 void QCPItemTracer::setSelectedPen(const QPen &pen)
22957 void QCPItemTracer::setSelectedPen(const QPen &pen)
23457 {
22958 {
23458 mSelectedPen = pen;
22959 mSelectedPen = pen;
23459 }
22960 }
23460
22961
23461 /*!
22962 /*!
@@ -23465,7 +22966,7 void QCPItemTracer::setSelectedPen(const
23465 */
22966 */
23466 void QCPItemTracer::setBrush(const QBrush &brush)
22967 void QCPItemTracer::setBrush(const QBrush &brush)
23467 {
22968 {
23468 mBrush = brush;
22969 mBrush = brush;
23469 }
22970 }
23470
22971
23471 /*!
22972 /*!
@@ -23475,7 +22976,7 void QCPItemTracer::setBrush(const QBrus
23475 */
22976 */
23476 void QCPItemTracer::setSelectedBrush(const QBrush &brush)
22977 void QCPItemTracer::setSelectedBrush(const QBrush &brush)
23477 {
22978 {
23478 mSelectedBrush = brush;
22979 mSelectedBrush = brush;
23479 }
22980 }
23480
22981
23481 /*!
22982 /*!
@@ -23484,7 +22985,7 void QCPItemTracer::setSelectedBrush(con
23484 */
22985 */
23485 void QCPItemTracer::setSize(double size)
22986 void QCPItemTracer::setSize(double size)
23486 {
22987 {
23487 mSize = size;
22988 mSize = size;
23488 }
22989 }
23489
22990
23490 /*!
22991 /*!
@@ -23495,7 +22996,7 void QCPItemTracer::setSize(double size)
23495 */
22996 */
23496 void QCPItemTracer::setStyle(QCPItemTracer::TracerStyle style)
22997 void QCPItemTracer::setStyle(QCPItemTracer::TracerStyle style)
23497 {
22998 {
23498 mStyle = style;
22999 mStyle = style;
23499 }
23000 }
23500
23001
23501 /*!
23002 /*!
@@ -23510,19 +23011,19 void QCPItemTracer::setStyle(QCPItemTrac
23510 */
23011 */
23511 void QCPItemTracer::setGraph(QCPGraph *graph)
23012 void QCPItemTracer::setGraph(QCPGraph *graph)
23512 {
23013 {
23513 if (graph)
23014 if (graph)
23514 {
23015 {
23515 if (graph->parentPlot() == mParentPlot)
23016 if (graph->parentPlot() == mParentPlot)
23516 {
23017 {
23517 position->setType(QCPItemPosition::ptPlotCoords);
23018 position->setType(QCPItemPosition::ptPlotCoords);
23518 position->setAxes(graph->keyAxis(), graph->valueAxis());
23019 position->setAxes(graph->keyAxis(), graph->valueAxis());
23519 mGraph = graph;
23020 mGraph = graph;
23520 updatePosition();
23021 updatePosition();
23521 } else
23022 } else
23522 qDebug() << Q_FUNC_INFO << "graph isn't in same QCustomPlot instance as this item";
23023 qDebug() << Q_FUNC_INFO << "graph isn't in same QCustomPlot instance as this item";
23523 } else
23024 } else
23524 {
23025 {
23525 mGraph = 0;
23026 mGraph = 0;
23526 }
23027 }
23527 }
23028 }
23528
23029
@@ -23537,7 +23038,7 void QCPItemTracer::setGraph(QCPGraph *g
23537 */
23038 */
23538 void QCPItemTracer::setGraphKey(double key)
23039 void QCPItemTracer::setGraphKey(double key)
23539 {
23040 {
23540 mGraphKey = key;
23041 mGraphKey = key;
23541 }
23042 }
23542
23043
23543 /*!
23044 /*!
@@ -23553,110 +23054,110 void QCPItemTracer::setGraphKey(double k
23553 */
23054 */
23554 void QCPItemTracer::setInterpolating(bool enabled)
23055 void QCPItemTracer::setInterpolating(bool enabled)
23555 {
23056 {
23556 mInterpolating = enabled;
23057 mInterpolating = enabled;
23557 }
23058 }
23558
23059
23559 /* inherits documentation from base class */
23060 /* inherits documentation from base class */
23560 double QCPItemTracer::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
23061 double QCPItemTracer::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
23561 {
23062 {
23562 Q_UNUSED(details)
23063 Q_UNUSED(details)
23563 if (onlySelectable && !mSelectable)
23064 if (onlySelectable && !mSelectable)
23564 return -1;
23065 return -1;
23565
23066
23566 QPointF center(position->pixelPoint());
23067 QPointF center(position->pixelPoint());
23567 double w = mSize/2.0;
23068 double w = mSize/2.0;
23568 QRect clip = clipRect();
23069 QRect clip = clipRect();
23569 switch (mStyle)
23070 switch (mStyle)
23570 {
23071 {
23571 case tsNone: return -1;
23072 case tsNone: return -1;
23572 case tsPlus:
23073 case tsPlus:
23573 {
23074 {
23574 if (clipRect().intersects(QRectF(center-QPointF(w, w), center+QPointF(w, w)).toRect()))
23075 if (clipRect().intersects(QRectF(center-QPointF(w, w), center+QPointF(w, w)).toRect()))
23575 return qSqrt(qMin(distSqrToLine(center+QPointF(-w, 0), center+QPointF(w, 0), pos),
23076 return qSqrt(qMin(distSqrToLine(center+QPointF(-w, 0), center+QPointF(w, 0), pos),
23576 distSqrToLine(center+QPointF(0, -w), center+QPointF(0, w), pos)));
23077 distSqrToLine(center+QPointF(0, -w), center+QPointF(0, w), pos)));
23577 break;
23078 break;
23578 }
23079 }
23579 case tsCrosshair:
23080 case tsCrosshair:
23580 {
23081 {
23581 return qSqrt(qMin(distSqrToLine(QPointF(clip.left(), center.y()), QPointF(clip.right(), center.y()), pos),
23082 return qSqrt(qMin(distSqrToLine(QPointF(clip.left(), center.y()), QPointF(clip.right(), center.y()), pos),
23582 distSqrToLine(QPointF(center.x(), clip.top()), QPointF(center.x(), clip.bottom()), pos)));
23083 distSqrToLine(QPointF(center.x(), clip.top()), QPointF(center.x(), clip.bottom()), pos)));
23583 }
23084 }
23584 case tsCircle:
23085 case tsCircle:
23585 {
23086 {
23586 if (clip.intersects(QRectF(center-QPointF(w, w), center+QPointF(w, w)).toRect()))
23087 if (clip.intersects(QRectF(center-QPointF(w, w), center+QPointF(w, w)).toRect()))
23587 {
23088 {
23588 // distance to border:
23089 // distance to border:
23589 double centerDist = QVector2D(center-pos).length();
23090 double centerDist = QVector2D(center-pos).length();
23590 double circleLine = w;
23091 double circleLine = w;
23591 double result = qAbs(centerDist-circleLine);
23092 double result = qAbs(centerDist-circleLine);
23592 // filled ellipse, allow click inside to count as hit:
23093 // filled ellipse, allow click inside to count as hit:
23593 if (result > mParentPlot->selectionTolerance()*0.99 && mBrush.style() != Qt::NoBrush && mBrush.color().alpha() != 0)
23094 if (result > mParentPlot->selectionTolerance()*0.99 && mBrush.style() != Qt::NoBrush && mBrush.color().alpha() != 0)
23594 {
23095 {
23595 if (centerDist <= circleLine)
23096 if (centerDist <= circleLine)
23596 result = mParentPlot->selectionTolerance()*0.99;
23097 result = mParentPlot->selectionTolerance()*0.99;
23597 }
23098 }
23598 return result;
23099 return result;
23599 }
23100 }
23600 break;
23101 break;
23601 }
23102 }
23602 case tsSquare:
23103 case tsSquare:
23603 {
23104 {
23604 if (clip.intersects(QRectF(center-QPointF(w, w), center+QPointF(w, w)).toRect()))
23105 if (clip.intersects(QRectF(center-QPointF(w, w), center+QPointF(w, w)).toRect()))
23605 {
23106 {
23606 QRectF rect = QRectF(center-QPointF(w, w), center+QPointF(w, w));
23107 QRectF rect = QRectF(center-QPointF(w, w), center+QPointF(w, w));
23607 bool filledRect = mBrush.style() != Qt::NoBrush && mBrush.color().alpha() != 0;
23108 bool filledRect = mBrush.style() != Qt::NoBrush && mBrush.color().alpha() != 0;
23608 return rectSelectTest(rect, pos, filledRect);
23109 return rectSelectTest(rect, pos, filledRect);
23609 }
23110 }
23610 break;
23111 break;
23611 }
23112 }
23612 }
23113 }
23613 return -1;
23114 return -1;
23614 }
23115 }
23615
23116
23616 /* inherits documentation from base class */
23117 /* inherits documentation from base class */
23617 void QCPItemTracer::draw(QCPPainter *painter)
23118 void QCPItemTracer::draw(QCPPainter *painter)
23618 {
23119 {
23619 updatePosition();
23120 updatePosition();
23620 if (mStyle == tsNone)
23121 if (mStyle == tsNone)
23621 return;
23122 return;
23622
23123
23623 painter->setPen(mainPen());
23124 painter->setPen(mainPen());
23624 painter->setBrush(mainBrush());
23125 painter->setBrush(mainBrush());
23625 QPointF center(position->pixelPoint());
23126 QPointF center(position->pixelPoint());
23626 double w = mSize/2.0;
23127 double w = mSize/2.0;
23627 QRect clip = clipRect();
23128 QRect clip = clipRect();
23628 switch (mStyle)
23129 switch (mStyle)
23629 {
23130 {
23630 case tsNone: return;
23131 case tsNone: return;
23631 case tsPlus:
23132 case tsPlus:
23632 {
23133 {
23633 if (clip.intersects(QRectF(center-QPointF(w, w), center+QPointF(w, w)).toRect()))
23134 if (clip.intersects(QRectF(center-QPointF(w, w), center+QPointF(w, w)).toRect()))
23634 {
23135 {
23635 painter->drawLine(QLineF(center+QPointF(-w, 0), center+QPointF(w, 0)));
23136 painter->drawLine(QLineF(center+QPointF(-w, 0), center+QPointF(w, 0)));
23636 painter->drawLine(QLineF(center+QPointF(0, -w), center+QPointF(0, w)));
23137 painter->drawLine(QLineF(center+QPointF(0, -w), center+QPointF(0, w)));
23637 }
23138 }
23638 break;
23139 break;
23639 }
23140 }
23640 case tsCrosshair:
23141 case tsCrosshair:
23641 {
23142 {
23642 if (center.y() > clip.top() && center.y() < clip.bottom())
23143 if (center.y() > clip.top() && center.y() < clip.bottom())
23643 painter->drawLine(QLineF(clip.left(), center.y(), clip.right(), center.y()));
23144 painter->drawLine(QLineF(clip.left(), center.y(), clip.right(), center.y()));
23644 if (center.x() > clip.left() && center.x() < clip.right())
23145 if (center.x() > clip.left() && center.x() < clip.right())
23645 painter->drawLine(QLineF(center.x(), clip.top(), center.x(), clip.bottom()));
23146 painter->drawLine(QLineF(center.x(), clip.top(), center.x(), clip.bottom()));
23646 break;
23147 break;
23647 }
23148 }
23648 case tsCircle:
23149 case tsCircle:
23649 {
23150 {
23650 if (clip.intersects(QRectF(center-QPointF(w, w), center+QPointF(w, w)).toRect()))
23151 if (clip.intersects(QRectF(center-QPointF(w, w), center+QPointF(w, w)).toRect()))
23651 painter->drawEllipse(center, w, w);
23152 painter->drawEllipse(center, w, w);
23652 break;
23153 break;
23653 }
23154 }
23654 case tsSquare:
23155 case tsSquare:
23655 {
23156 {
23656 if (clip.intersects(QRectF(center-QPointF(w, w), center+QPointF(w, w)).toRect()))
23157 if (clip.intersects(QRectF(center-QPointF(w, w), center+QPointF(w, w)).toRect()))
23657 painter->drawRect(QRectF(center-QPointF(w, w), center+QPointF(w, w)));
23158 painter->drawRect(QRectF(center-QPointF(w, w), center+QPointF(w, w)));
23658 break;
23159 break;
23659 }
23160 }
23660 }
23161 }
23661 }
23162 }
23662
23163
@@ -23674,49 +23175,49 void QCPItemTracer::draw(QCPPainter *pai
23674 */
23175 */
23675 void QCPItemTracer::updatePosition()
23176 void QCPItemTracer::updatePosition()
23676 {
23177 {
23677 if (mGraph)
23178 if (mGraph)
23678 {
23179 {
23679 if (mParentPlot->hasPlottable(mGraph))
23180 if (mParentPlot->hasPlottable(mGraph))
23680 {
23181 {
23681 if (mGraph->data()->size() > 1)
23182 if (mGraph->data()->size() > 1)
23682 {
23183 {
23683 QCPDataMap::const_iterator first = mGraph->data()->constBegin();
23184 QCPDataMap::const_iterator first = mGraph->data()->constBegin();
23684 QCPDataMap::const_iterator last = mGraph->data()->constEnd()-1;
23185 QCPDataMap::const_iterator last = mGraph->data()->constEnd()-1;
23685 if (mGraphKey < first.key())
23186 if (mGraphKey < first.key())
23686 position->setCoords(first.key(), first.value().value);
23187 position->setCoords(first.key(), first.value().value);
23687 else if (mGraphKey > last.key())
23188 else if (mGraphKey > last.key())
23688 position->setCoords(last.key(), last.value().value);
23189 position->setCoords(last.key(), last.value().value);
23689 else
23190 else
23690 {
23191 {
23691 QCPDataMap::const_iterator it = mGraph->data()->lowerBound(mGraphKey);
23192 QCPDataMap::const_iterator it = mGraph->data()->lowerBound(mGraphKey);
23692 if (it != first) // mGraphKey is somewhere between iterators
23193 if (it != first) // mGraphKey is somewhere between iterators
23693 {
23194 {
23694 QCPDataMap::const_iterator prevIt = it-1;
23195 QCPDataMap::const_iterator prevIt = it-1;
23695 if (mInterpolating)
23196 if (mInterpolating)
23696 {
23197 {
23697 // interpolate between iterators around mGraphKey:
23198 // interpolate between iterators around mGraphKey:
23698 double slope = 0;
23199 double slope = 0;
23699 if (!qFuzzyCompare((double)it.key(), (double)prevIt.key()))
23200 if (!qFuzzyCompare((double)it.key(), (double)prevIt.key()))
23700 slope = (it.value().value-prevIt.value().value)/(it.key()-prevIt.key());
23201 slope = (it.value().value-prevIt.value().value)/(it.key()-prevIt.key());
23701 position->setCoords(mGraphKey, (mGraphKey-prevIt.key())*slope+prevIt.value().value);
23202 position->setCoords(mGraphKey, (mGraphKey-prevIt.key())*slope+prevIt.value().value);
23702 } else
23203 } else
23703 {
23204 {
23704 // find iterator with key closest to mGraphKey:
23205 // find iterator with key closest to mGraphKey:
23705 if (mGraphKey < (prevIt.key()+it.key())*0.5)
23206 if (mGraphKey < (prevIt.key()+it.key())*0.5)
23706 it = prevIt;
23207 it = prevIt;
23707 position->setCoords(it.key(), it.value().value);
23208 position->setCoords(it.key(), it.value().value);
23708 }
23209 }
23709 } else // mGraphKey is exactly on first iterator
23210 } else // mGraphKey is exactly on first iterator
23710 position->setCoords(it.key(), it.value().value);
23211 position->setCoords(it.key(), it.value().value);
23711 }
23212 }
23712 } else if (mGraph->data()->size() == 1)
23213 } else if (mGraph->data()->size() == 1)
23713 {
23214 {
23714 QCPDataMap::const_iterator it = mGraph->data()->constBegin();
23215 QCPDataMap::const_iterator it = mGraph->data()->constBegin();
23715 position->setCoords(it.key(), it.value().value);
23216 position->setCoords(it.key(), it.value().value);
23716 } else
23217 } else
23717 qDebug() << Q_FUNC_INFO << "graph has no data";
23218 qDebug() << Q_FUNC_INFO << "graph has no data";
23718 } else
23219 } else
23719 qDebug() << Q_FUNC_INFO << "graph not contained in QCustomPlot instance (anymore)";
23220 qDebug() << Q_FUNC_INFO << "graph not contained in QCustomPlot instance (anymore)";
23720 }
23221 }
23721 }
23222 }
23722
23223
@@ -23727,7 +23228,7 void QCPItemTracer::updatePosition()
23727 */
23228 */
23728 QPen QCPItemTracer::mainPen() const
23229 QPen QCPItemTracer::mainPen() const
23729 {
23230 {
23730 return mSelected ? mSelectedPen : mPen;
23231 return mSelected ? mSelectedPen : mPen;
23731 }
23232 }
23732
23233
23733 /*! \internal
23234 /*! \internal
@@ -23737,7 +23238,7 QPen QCPItemTracer::mainPen() const
23737 */
23238 */
23738 QBrush QCPItemTracer::mainBrush() const
23239 QBrush QCPItemTracer::mainBrush() const
23739 {
23240 {
23740 return mSelected ? mSelectedBrush : mBrush;
23241 return mSelected ? mSelectedBrush : mBrush;
23741 }
23242 }
23742
23243
23743
23244
@@ -23771,18 +23272,18 QBrush QCPItemTracer::mainBrush() const
23771 The constructed item can be added to the plot with QCustomPlot::addItem.
23272 The constructed item can be added to the plot with QCustomPlot::addItem.
23772 */
23273 */
23773 QCPItemBracket::QCPItemBracket(QCustomPlot *parentPlot) :
23274 QCPItemBracket::QCPItemBracket(QCustomPlot *parentPlot) :
23774 QCPAbstractItem(parentPlot),
23275 QCPAbstractItem(parentPlot),
23775 left(createPosition(QLatin1String("left"))),
23276 left(createPosition(QLatin1String("left"))),
23776 right(createPosition(QLatin1String("right"))),
23277 right(createPosition(QLatin1String("right"))),
23777 center(createAnchor(QLatin1String("center"), aiCenter))
23278 center(createAnchor(QLatin1String("center"), aiCenter))
23778 {
23279 {
23779 left->setCoords(0, 0);
23280 left->setCoords(0, 0);
23780 right->setCoords(1, 1);
23281 right->setCoords(1, 1);
23781
23282
23782 setPen(QPen(Qt::black));
23283 setPen(QPen(Qt::black));
23783 setSelectedPen(QPen(Qt::blue, 2));
23284 setSelectedPen(QPen(Qt::blue, 2));
23784 setLength(8);
23285 setLength(8);
23785 setStyle(bsCalligraphic);
23286 setStyle(bsCalligraphic);
23786 }
23287 }
23787
23288
23788 QCPItemBracket::~QCPItemBracket()
23289 QCPItemBracket::~QCPItemBracket()
@@ -23800,7 +23301,7 QCPItemBracket::~QCPItemBracket()
23800 */
23301 */
23801 void QCPItemBracket::setPen(const QPen &pen)
23302 void QCPItemBracket::setPen(const QPen &pen)
23802 {
23303 {
23803 mPen = pen;
23304 mPen = pen;
23804 }
23305 }
23805
23306
23806 /*!
23307 /*!
@@ -23810,7 +23311,7 void QCPItemBracket::setPen(const QPen &
23810 */
23311 */
23811 void QCPItemBracket::setSelectedPen(const QPen &pen)
23312 void QCPItemBracket::setSelectedPen(const QPen &pen)
23812 {
23313 {
23813 mSelectedPen = pen;
23314 mSelectedPen = pen;
23814 }
23315 }
23815
23316
23816 /*!
23317 /*!
@@ -23823,7 +23324,7 void QCPItemBracket::setSelectedPen(cons
23823 */
23324 */
23824 void QCPItemBracket::setLength(double length)
23325 void QCPItemBracket::setLength(double length)
23825 {
23326 {
23826 mLength = length;
23327 mLength = length;
23827 }
23328 }
23828
23329
23829 /*!
23330 /*!
@@ -23833,60 +23334,60 void QCPItemBracket::setLength(double le
23833 */
23334 */
23834 void QCPItemBracket::setStyle(QCPItemBracket::BracketStyle style)
23335 void QCPItemBracket::setStyle(QCPItemBracket::BracketStyle style)
23835 {
23336 {
23836 mStyle = style;
23337 mStyle = style;
23837 }
23338 }
23838
23339
23839 /* inherits documentation from base class */
23340 /* inherits documentation from base class */
23840 double QCPItemBracket::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
23341 double QCPItemBracket::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
23841 {
23342 {
23842 Q_UNUSED(details)
23343 Q_UNUSED(details)
23843 if (onlySelectable && !mSelectable)
23344 if (onlySelectable && !mSelectable)
23844 return -1;
23345 return -1;
23845
23346
23846 QVector2D leftVec(left->pixelPoint());
23347 QVector2D leftVec(left->pixelPoint());
23847 QVector2D rightVec(right->pixelPoint());
23348 QVector2D rightVec(right->pixelPoint());
23848 if (leftVec.toPoint() == rightVec.toPoint())
23349 if (leftVec.toPoint() == rightVec.toPoint())
23849 return -1;
23350 return -1;
23850
23351
23851 QVector2D widthVec = (rightVec-leftVec)*0.5f;
23352 QVector2D widthVec = (rightVec-leftVec)*0.5f;
23852 QVector2D lengthVec(-widthVec.y(), widthVec.x());
23353 QVector2D lengthVec(-widthVec.y(), widthVec.x());
23853 lengthVec = lengthVec.normalized()*mLength;
23354 lengthVec = lengthVec.normalized()*mLength;
23854 QVector2D centerVec = (rightVec+leftVec)*0.5f-lengthVec;
23355 QVector2D centerVec = (rightVec+leftVec)*0.5f-lengthVec;
23855
23356
23856 return qSqrt(distSqrToLine((centerVec-widthVec).toPointF(), (centerVec+widthVec).toPointF(), pos));
23357 return qSqrt(distSqrToLine((centerVec-widthVec).toPointF(), (centerVec+widthVec).toPointF(), pos));
23857 }
23358 }
23858
23359
23859 /* inherits documentation from base class */
23360 /* inherits documentation from base class */
23860 void QCPItemBracket::draw(QCPPainter *painter)
23361 void QCPItemBracket::draw(QCPPainter *painter)
23861 {
23362 {
23862 QVector2D leftVec(left->pixelPoint());
23363 QVector2D leftVec(left->pixelPoint());
23863 QVector2D rightVec(right->pixelPoint());
23364 QVector2D rightVec(right->pixelPoint());
23864 if (leftVec.toPoint() == rightVec.toPoint())
23365 if (leftVec.toPoint() == rightVec.toPoint())
23865 return;
23366 return;
23866
23367
23867 QVector2D widthVec = (rightVec-leftVec)*0.5f;
23368 QVector2D widthVec = (rightVec-leftVec)*0.5f;
23868 QVector2D lengthVec(-widthVec.y(), widthVec.x());
23369 QVector2D lengthVec(-widthVec.y(), widthVec.x());
23869 lengthVec = lengthVec.normalized()*mLength;
23370 lengthVec = lengthVec.normalized()*mLength;
23870 QVector2D centerVec = (rightVec+leftVec)*0.5f-lengthVec;
23371 QVector2D centerVec = (rightVec+leftVec)*0.5f-lengthVec;
23871
23372
23872 QPolygon boundingPoly;
23373 QPolygon boundingPoly;
23873 boundingPoly << leftVec.toPoint() << rightVec.toPoint()
23374 boundingPoly << leftVec.toPoint() << rightVec.toPoint()
23874 << (rightVec-lengthVec).toPoint() << (leftVec-lengthVec).toPoint();
23375 << (rightVec-lengthVec).toPoint() << (leftVec-lengthVec).toPoint();
23875 QRect clip = clipRect().adjusted(-mainPen().widthF(), -mainPen().widthF(), mainPen().widthF(), mainPen().widthF());
23376 QRect clip = clipRect().adjusted(-mainPen().widthF(), -mainPen().widthF(), mainPen().widthF(), mainPen().widthF());
23876 if (clip.intersects(boundingPoly.boundingRect()))
23377 if (clip.intersects(boundingPoly.boundingRect()))
23877 {
23378 {
23878 painter->setPen(mainPen());
23379 painter->setPen(mainPen());
23879 switch (mStyle)
23380 switch (mStyle)
23880 {
23381 {
23881 case bsSquare:
23382 case bsSquare:
23882 {
23383 {
23883 painter->drawLine((centerVec+widthVec).toPointF(), (centerVec-widthVec).toPointF());
23384 painter->drawLine((centerVec+widthVec).toPointF(), (centerVec-widthVec).toPointF());
23884 painter->drawLine((centerVec+widthVec).toPointF(), (centerVec+widthVec+lengthVec).toPointF());
23385 painter->drawLine((centerVec+widthVec).toPointF(), (centerVec+widthVec+lengthVec).toPointF());
23885 painter->drawLine((centerVec-widthVec).toPointF(), (centerVec-widthVec+lengthVec).toPointF());
23386 painter->drawLine((centerVec-widthVec).toPointF(), (centerVec-widthVec+lengthVec).toPointF());
23886 break;
23387 break;
23887 }
23388 }
23888 case bsRound:
23389 case bsRound:
23889 {
23390 {
23890 painter->setBrush(Qt::NoBrush);
23391 painter->setBrush(Qt::NoBrush);
23891 QPainterPath path;
23392 QPainterPath path;
23892 path.moveTo((centerVec+widthVec+lengthVec).toPointF());
23393 path.moveTo((centerVec+widthVec+lengthVec).toPointF());
@@ -23894,9 +23395,9 void QCPItemBracket::draw(QCPPainter *pa
23894 path.cubicTo((centerVec-widthVec).toPointF(), (centerVec-widthVec).toPointF(), (centerVec-widthVec+lengthVec).toPointF());
23395 path.cubicTo((centerVec-widthVec).toPointF(), (centerVec-widthVec).toPointF(), (centerVec-widthVec+lengthVec).toPointF());
23895 painter->drawPath(path);
23396 painter->drawPath(path);
23896 break;
23397 break;
23897 }
23398 }
23898 case bsCurly:
23399 case bsCurly:
23899 {
23400 {
23900 painter->setBrush(Qt::NoBrush);
23401 painter->setBrush(Qt::NoBrush);
23901 QPainterPath path;
23402 QPainterPath path;
23902 path.moveTo((centerVec+widthVec+lengthVec).toPointF());
23403 path.moveTo((centerVec+widthVec+lengthVec).toPointF());
@@ -23904,9 +23405,9 void QCPItemBracket::draw(QCPPainter *pa
23904 path.cubicTo((centerVec-0.4f*widthVec+lengthVec).toPointF(), (centerVec-widthVec-lengthVec*0.8f).toPointF(), (centerVec-widthVec+lengthVec).toPointF());
23405 path.cubicTo((centerVec-0.4f*widthVec+lengthVec).toPointF(), (centerVec-widthVec-lengthVec*0.8f).toPointF(), (centerVec-widthVec+lengthVec).toPointF());
23905 painter->drawPath(path);
23406 painter->drawPath(path);
23906 break;
23407 break;
23907 }
23408 }
23908 case bsCalligraphic:
23409 case bsCalligraphic:
23909 {
23410 {
23910 painter->setPen(Qt::NoPen);
23411 painter->setPen(Qt::NoPen);
23911 painter->setBrush(QBrush(mainPen().color()));
23412 painter->setBrush(QBrush(mainPen().color()));
23912 QPainterPath path;
23413 QPainterPath path;
@@ -23920,7 +23421,7 void QCPItemBracket::draw(QCPPainter *pa
23920
23421
23921 painter->drawPath(path);
23422 painter->drawPath(path);
23922 break;
23423 break;
23923 }
23424 }
23924 }
23425 }
23925 }
23426 }
23926 }
23427 }
@@ -23928,23 +23429,23 void QCPItemBracket::draw(QCPPainter *pa
23928 /* inherits documentation from base class */
23429 /* inherits documentation from base class */
23929 QPointF QCPItemBracket::anchorPixelPoint(int anchorId) const
23430 QPointF QCPItemBracket::anchorPixelPoint(int anchorId) const
23930 {
23431 {
23931 QVector2D leftVec(left->pixelPoint());
23432 QVector2D leftVec(left->pixelPoint());
23932 QVector2D rightVec(right->pixelPoint());
23433 QVector2D rightVec(right->pixelPoint());
23933 if (leftVec.toPoint() == rightVec.toPoint())
23434 if (leftVec.toPoint() == rightVec.toPoint())
23934 return leftVec.toPointF();
23435 return leftVec.toPointF();
23935
23436
23936 QVector2D widthVec = (rightVec-leftVec)*0.5f;
23437 QVector2D widthVec = (rightVec-leftVec)*0.5f;
23937 QVector2D lengthVec(-widthVec.y(), widthVec.x());
23438 QVector2D lengthVec(-widthVec.y(), widthVec.x());
23938 lengthVec = lengthVec.normalized()*mLength;
23439 lengthVec = lengthVec.normalized()*mLength;
23939 QVector2D centerVec = (rightVec+leftVec)*0.5f-lengthVec;
23440 QVector2D centerVec = (rightVec+leftVec)*0.5f-lengthVec;
23940
23441
23941 switch (anchorId)
23442 switch (anchorId)
23942 {
23443 {
23943 case aiCenter:
23444 case aiCenter:
23944 return centerVec.toPointF();
23445 return centerVec.toPointF();
23945 }
23446 }
23946 qDebug() << Q_FUNC_INFO << "invalid anchorId" << anchorId;
23447 qDebug() << Q_FUNC_INFO << "invalid anchorId" << anchorId;
23947 return QPointF();
23448 return QPointF();
23948 }
23449 }
23949
23450
23950 /*! \internal
23451 /*! \internal
@@ -23954,6 +23455,6 QPointF QCPItemBracket::anchorPixelPoint
23954 */
23455 */
23955 QPen QCPItemBracket::mainPen() const
23456 QPen QCPItemBracket::mainPen() const
23956 {
23457 {
23957 return mSelected ? mSelectedPen : mPen;
23458 return mSelected ? mSelectedPen : mPen;
23958 }
23459 }
23959
23460
@@ -1862,7 +1862,6 protected:
1862 QCPLayer *mCurrentLayer;
1862 QCPLayer *mCurrentLayer;
1863 QCP::PlottingHints mPlottingHints;
1863 QCP::PlottingHints mPlottingHints;
1864 Qt::KeyboardModifier mMultiSelectModifier;
1864 Qt::KeyboardModifier mMultiSelectModifier;
1865 bool mUseFastVectors;
1866
1865
1867 // non-property members:
1866 // non-property members:
1868 QPixmap mPaintBuffer;
1867 QPixmap mPaintBuffer;
@@ -2539,12 +2538,10 public:
2539 bool errorBarSkipSymbol() const { return mErrorBarSkipSymbol; }
2538 bool errorBarSkipSymbol() const { return mErrorBarSkipSymbol; }
2540 QCPGraph *channelFillGraph() const { return mChannelFillGraph.data(); }
2539 QCPGraph *channelFillGraph() const { return mChannelFillGraph.data(); }
2541 bool adaptiveSampling() const { return mAdaptiveSampling; }
2540 bool adaptiveSampling() const { return mAdaptiveSampling; }
2542 bool useFastVectors() const { return mUseFastVectors; }
2543
2541
2544 // setters:
2542 // setters:
2545 void setData(QCPDataMap *data, bool copy=false);
2543 void setData(QCPDataMap *data, bool copy=false);
2546 void setData(const QVector<double> &key, const QVector<double> &value);
2544 void setData(const QVector<double> &key, const QVector<double> &value);
2547 void setData(QVector<QCPData> *data);
2548 void setDataKeyError(const QVector<double> &key, const QVector<double> &value, const QVector<double> &keyError);
2545 void setDataKeyError(const QVector<double> &key, const QVector<double> &value, const QVector<double> &keyError);
2549 void setDataKeyError(const QVector<double> &key, const QVector<double> &value, const QVector<double> &keyErrorMinus, const QVector<double> &keyErrorPlus);
2546 void setDataKeyError(const QVector<double> &key, const QVector<double> &value, const QVector<double> &keyErrorMinus, const QVector<double> &keyErrorPlus);
2550 void setDataValueError(const QVector<double> &key, const QVector<double> &value, const QVector<double> &valueError);
2547 void setDataValueError(const QVector<double> &key, const QVector<double> &value, const QVector<double> &valueError);
@@ -2559,7 +2556,6 public:
2559 void setErrorBarSkipSymbol(bool enabled);
2556 void setErrorBarSkipSymbol(bool enabled);
2560 void setChannelFillGraph(QCPGraph *targetGraph);
2557 void setChannelFillGraph(QCPGraph *targetGraph);
2561 void setAdaptiveSampling(bool enabled);
2558 void setAdaptiveSampling(bool enabled);
2562 void setUseFastVectors(bool useFastVectors);
2563
2559
2564 // non-property methods:
2560 // non-property methods:
2565 void addData(const QCPDataMap &dataMap);
2561 void addData(const QCPDataMap &dataMap);
@@ -2584,7 +2580,6 public:
2584 protected:
2580 protected:
2585 // property members:
2581 // property members:
2586 QCPDataMap *mData;
2582 QCPDataMap *mData;
2587 QVector<QCPData>* mDataVector;
2588 QPen mErrorPen;
2583 QPen mErrorPen;
2589 LineStyle mLineStyle;
2584 LineStyle mLineStyle;
2590 QCPScatterStyle mScatterStyle;
2585 QCPScatterStyle mScatterStyle;
@@ -2593,7 +2588,6 protected:
2593 bool mErrorBarSkipSymbol;
2588 bool mErrorBarSkipSymbol;
2594 QPointer<QCPGraph> mChannelFillGraph;
2589 QPointer<QCPGraph> mChannelFillGraph;
2595 bool mAdaptiveSampling;
2590 bool mAdaptiveSampling;
2596 bool mUseFastVectors;
2597
2591
2598 // reimplemented virtual methods:
2592 // reimplemented virtual methods:
2599 virtual void draw(QCPPainter *painter);
2593 virtual void draw(QCPPainter *painter);
@@ -2601,9 +2595,8 protected:
2601 virtual QCPRange getKeyRange(bool &foundRange, SignDomain inSignDomain=sdBoth) const;
2595 virtual QCPRange getKeyRange(bool &foundRange, SignDomain inSignDomain=sdBoth) const;
2602 virtual QCPRange getValueRange(bool &foundRange, SignDomain inSignDomain=sdBoth) const;
2596 virtual QCPRange getValueRange(bool &foundRange, SignDomain inSignDomain=sdBoth) const;
2603 virtual QCPRange getKeyRange(bool &foundRange, SignDomain inSignDomain, bool includeErrors) const; // overloads base class interface
2597 virtual QCPRange getKeyRange(bool &foundRange, SignDomain inSignDomain, bool includeErrors) const; // overloads base class interface
2604 virtual QCPRange getKeyRangeVector(bool &foundRange, SignDomain inSignDomain, bool includeErrors) const; // overloads base class interface
2605 virtual QCPRange getValueRange(bool &foundRange, SignDomain inSignDomain, bool includeErrors) const; // overloads base class interface
2598 virtual QCPRange getValueRange(bool &foundRange, SignDomain inSignDomain, bool includeErrors) const; // overloads base class interface
2606 virtual QCPRange getValueRangeVector(bool &foundRange, SignDomain inSignDomain, bool includeErrors) const;
2599
2607 // introduced virtual methods:
2600 // introduced virtual methods:
2608 virtual void drawFill(QCPPainter *painter, QVector<QPointF> *lineData) const;
2601 virtual void drawFill(QCPPainter *painter, QVector<QPointF> *lineData) const;
2609 virtual void drawScatterPlot(QCPPainter *painter, QVector<QCPData> *scatterData) const;
2602 virtual void drawScatterPlot(QCPPainter *painter, QVector<QCPData> *scatterData) const;
@@ -2612,7 +2605,6 protected:
2612
2605
2613 // non-virtual methods:
2606 // non-virtual methods:
2614 void getPreparedData(QVector<QCPData> *lineData, QVector<QCPData> *scatterData) const;
2607 void getPreparedData(QVector<QCPData> *lineData, QVector<QCPData> *scatterData) const;
2615 void getPreparedDataVector(QVector<QCPData> *lineData, QVector<QCPData> *scatterData) const;
2616 void getPlotData(QVector<QPointF> *lineData, QVector<QCPData> *scatterData) const;
2608 void getPlotData(QVector<QPointF> *lineData, QVector<QCPData> *scatterData) const;
2617 void getScatterPlotData(QVector<QCPData> *scatterData) const;
2609 void getScatterPlotData(QVector<QCPData> *scatterData) const;
2618 void getLinePlotData(QVector<QPointF> *linePixelData, QVector<QCPData> *scatterData) const;
2610 void getLinePlotData(QVector<QPointF> *linePixelData, QVector<QCPData> *scatterData) const;
@@ -2622,9 +2614,7 protected:
2622 void getImpulsePlotData(QVector<QPointF> *linePixelData, QVector<QCPData> *scatterData) const;
2614 void getImpulsePlotData(QVector<QPointF> *linePixelData, QVector<QCPData> *scatterData) const;
2623 void drawError(QCPPainter *painter, double x, double y, const QCPData &data) const;
2615 void drawError(QCPPainter *painter, double x, double y, const QCPData &data) const;
2624 void getVisibleDataBounds(QCPDataMap::const_iterator &lower, QCPDataMap::const_iterator &upper) const;
2616 void getVisibleDataBounds(QCPDataMap::const_iterator &lower, QCPDataMap::const_iterator &upper) const;
2625 void getVisibleDataBoundsVector(QVector<QCPData>::const_iterator &lower, QVector<QCPData>::const_iterator &upper) const;
2626 int countDataInBounds(const QCPDataMap::const_iterator &lower, const QCPDataMap::const_iterator &upper, int maxCount) const;
2617 int countDataInBounds(const QCPDataMap::const_iterator &lower, const QCPDataMap::const_iterator &upper, int maxCount) const;
2627 int countDataInBoundsVector(const QVector<QCPData>::const_iterator &lower, const QVector<QCPData>::const_iterator &upper, int maxCount) const;
2628 void addFillBasePoints(QVector<QPointF> *lineData) const;
2618 void addFillBasePoints(QVector<QPointF> *lineData) const;
2629 void removeFillBasePoints(QVector<QPointF> *lineData) const;
2619 void removeFillBasePoints(QVector<QPointF> *lineData) const;
2630 QPointF lowerFillBasePoint(double lowerKey) const;
2620 QPointF lowerFillBasePoint(double lowerKey) const;
@@ -28,7 +28,7
28 SocExplorerPlot::SocExplorerPlot(QWidget *parent) :
28 SocExplorerPlot::SocExplorerPlot(QWidget *parent) :
29 QWidget(parent), mRubberBand(new QRubberBand(QRubberBand::Rectangle, this))
29 QWidget(parent), mRubberBand(new QRubberBand(QRubberBand::Rectangle, this))
30 {
30 {
31 this->m_plot = new QCustomPlot(this);
31 this->m_plot = new QCustomPlotVect(this);
32 this->m_plot->setInteractions(QCP::iRangeDrag | QCP::iSelectAxes |
32 this->m_plot->setInteractions(QCP::iRangeDrag | QCP::iSelectAxes |
33 QCP::iSelectLegend | QCP::iSelectPlottables);
33 QCP::iSelectLegend | QCP::iSelectPlottables);
34 this->m_plot->axisRect()->setRangeDrag(Qt::Horizontal|Qt::Vertical);
34 this->m_plot->axisRect()->setRangeDrag(Qt::Horizontal|Qt::Vertical);
@@ -85,6 +85,18 void SocExplorerPlot::exportToPDF(const
85 qcpPainter.end();
85 qcpPainter.end();
86 }
86 }
87
87
88 void SocExplorerPlot::addAction(SocExplorerPlotActions *action)
89 {
90 this->m_actions.append(action);
91 QWidget::addAction((QAction*)action);
92 }
93
94 QVector<QCPData> *SocExplorerPlot::getVisibleData(int graphIndex)
95 {
96 QVector<QCPData> *wholeData=((QCPGraphVect*)m_plot->graph(graphIndex))->data();
97 // m_plot->xAxis->
98 }
99
88 void SocExplorerPlot::setTitle(QString title)
100 void SocExplorerPlot::setTitle(QString title)
89 {
101 {
90 Q_UNUSED(title)
102 Q_UNUSED(title)
@@ -144,7 +156,8 void SocExplorerPlot::setAdaptativeSampl
144
156
145 void SocExplorerPlot::setUseFastVector(int graphIndex, bool enable)
157 void SocExplorerPlot::setUseFastVector(int graphIndex, bool enable)
146 {
158 {
147 this->m_plot->graph(graphIndex)->setUseFastVectors(enable);
159 // TODO deprecated
160 // this->m_plot->graph(graphIndex)->setUseFastVectors(enable);
148 }
161 }
149
162
150 int SocExplorerPlot::addGraph()
163 int SocExplorerPlot::addGraph()
@@ -155,7 +168,12 int SocExplorerPlot::addGraph()
155
168
156 bool SocExplorerPlot::removeGraph(int graphIndex)
169 bool SocExplorerPlot::removeGraph(int graphIndex)
157 {
170 {
158 return this->m_plot->removeGraph(graphIndex);
171 return this->m_plot->removeGraph(graphIndex);
172 }
173
174 int SocExplorerPlot::graphCount()
175 {
176 return m_plot->graphCount();
159 }
177 }
160
178
161 void SocExplorerPlot::removeAllGraphs()
179 void SocExplorerPlot::removeAllGraphs()
@@ -226,7 +244,7 void SocExplorerPlot::setGraphData(int g
226 {
244 {
227 if((graphIndex<this->m_plot->graphCount()))// && (x.at(0).type()==QVariant::Double))
245 if((graphIndex<this->m_plot->graphCount()))// && (x.at(0).type()==QVariant::Double))
228 {
246 {
229 this->m_plot->graph(graphIndex)->setData(data);
247 ((QCPGraphVect*)this->m_plot->graph(graphIndex))->setData(data);
230 }
248 }
231 if(replot)
249 if(replot)
232 this->m_plot->replot();
250 this->m_plot->replot();
@@ -25,9 +25,37
25 #include <QWidget>
25 #include <QWidget>
26 #include <QGridLayout>
26 #include <QGridLayout>
27 #include <qcustomplot.h>
27 #include <qcustomplot.h>
28 #include <qcustomplotvect.h>
28 #include <QRubberBand>
29 #include <QRubberBand>
29 #include <QPoint>
30 #include <QPoint>
30
31
32 class SocExplorerPlotActions : public QAction
33 {
34 Q_OBJECT
35 public:
36 SocExplorerPlotActions(const QString &text,int PID,QObject* parent=0)
37 :QAction(text,parent)
38 {
39 setPID(PID);
40 connect(this,SIGNAL(triggered()),this,SLOT(trigger()));
41 }
42 SocExplorerPlotActions(const QIcon &icon, const QString &text,int PID, QObject* parent)
43 :QAction(icon,text,parent)
44 {
45 setPID(PID);
46 connect(this,SIGNAL(triggered()),this,SLOT(trigger()));
47 }
48 ~SocExplorerPlotActions(){}
49 void setPID(int PID){this->m_PID=PID;}
50 int PID(){return m_PID;}
51 private slots:
52 void trigger(){emit triggered(m_PID);}
53 signals:
54 void triggered(int PID);
55 private:
56 int m_PID;
57 };
58
31 class SocExplorerPlot : public QWidget
59 class SocExplorerPlot : public QWidget
32 {
60 {
33 Q_OBJECT
61 Q_OBJECT
@@ -46,6 +74,7 public:
46 void setUseFastVector(int graphIndex,bool enable);
74 void setUseFastVector(int graphIndex,bool enable);
47 int addGraph();
75 int addGraph();
48 bool removeGraph(int graphIndex);
76 bool removeGraph(int graphIndex);
77 int graphCount();
49 void removeAllGraphs();
78 void removeAllGraphs();
50 void setGraphName(int graphIndex,QString name);
79 void setGraphName(int graphIndex,QString name);
51 void setGraphData(int graphIndex, QList<QVariant> x, QList<QVariant> y);
80 void setGraphData(int graphIndex, QList<QVariant> x, QList<QVariant> y);
@@ -63,6 +92,10 public:
63 void replot();
92 void replot();
64 void exportToSVG(const QString& fileName);
93 void exportToSVG(const QString& fileName);
65 void exportToPDF(const QString& fileName);
94 void exportToPDF(const QString& fileName);
95 void addAction(SocExplorerPlotActions* action);
96 int PID(){return m_PID;}
97 void setPID(int PID){m_PID = PID;}
98 QVector<QCPData>* getVisibleData(int graphIndex);
66 signals:
99 signals:
67 void titleChanged(const QString& newTitle);
100 void titleChanged(const QString& newTitle);
68 public slots:
101 public slots:
@@ -78,7 +111,7 protected:
78 private:
111 private:
79 void zoom(double factor, int center, Qt::Orientation orientation);
112 void zoom(double factor, int center, Qt::Orientation orientation);
80 void move(double factor, Qt::Orientation orientation);
113 void move(double factor, Qt::Orientation orientation);
81 QCustomPlot* m_plot;
114 QCustomPlotVect* m_plot;
82 QGridLayout* m_mainlayout;
115 QGridLayout* m_mainlayout;
83 bool ctrl_hold;
116 bool ctrl_hold;
84 bool shift_hold;
117 bool shift_hold;
@@ -89,6 +122,8 private:
89 bool mZoomMode;
122 bool mZoomMode;
90 QRubberBand * mRubberBand;
123 QRubberBand * mRubberBand;
91 QPoint mOrigin;
124 QPoint mOrigin;
125 QList<SocExplorerPlotActions*> m_actions;
126 int m_PID;
92 };
127 };
93
128
94 #endif // SOCEXPLORERPLOT_H
129 #endif // SOCEXPLORERPLOT_H
@@ -78,15 +78,15 MainWindow::~MainWindow()
78 delete ui;
78 delete ui;
79 }
79 }
80
80
81 QString MainWindow::getFilePath(const QString &name)
81 //QString MainWindow::getFilePath(const QString &name)
82 {
82 //{
83 // for(int i=0;i<this->folderViews.count();i++)
83 //// for(int i=0;i<this->folderViews.count();i++)
84 // {
84 //// {
85 // if(folderViews.at(i)->isDraging(name))
85 //// if(folderViews.at(i)->isDraging(name))
86 // return folderViews.at(i)->currentFolder();
86 //// return folderViews.at(i)->currentFolder();
87 // }
87 //// }
88 return "";
88 // return "";
89 }
89 //}
90
90
91
91
92
92
@@ -30,7 +30,6
30 #include <QListWidgetItem>
30 #include <QListWidgetItem>
31 #include <QVBoxLayout>
31 #include <QVBoxLayout>
32 #include <QWidget>
32 #include <QWidget>
33 #include "folderview.h"
34 #include "abstractfileloader.h"
33 #include "abstractfileloader.h"
35 #include "cassiniindexfileviewer.h"
34 #include "cassiniindexfileviewer.h"
36 #include <downloadhistory.h>
35 #include <downloadhistory.h>
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now