##// END OF EJS Templates
setLabelFormat bug fixed in QValueAxis
Marek Rosa -
r2268:2fcc3c0fd3b6
parent child
Show More
@@ -1,476 +1,486
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "chartaxis_p.h"
22 22 #include "qabstractaxis.h"
23 23 #include "qabstractaxis_p.h"
24 24 #include "chartpresenter_p.h"
25 25 #include "chartlayout_p.h"
26 26 #include "domain_p.h"
27 27 #include <qmath.h>
28 28 #include <QDateTime>
29 29 #include <QValueAxis>
30 30 #include <QGraphicsLayout>
31 31 #include <QFontMetrics>
32 32
33 33 QTCOMMERCIALCHART_BEGIN_NAMESPACE
34 34
35 35 ChartAxis::ChartAxis(QAbstractAxis *axis, ChartPresenter *presenter, bool intervalAxis)
36 36 : ChartElement(presenter),
37 37 m_chartAxis(axis),
38 38 m_labelsAngle(0),
39 39 m_grid(new QGraphicsItemGroup(presenter->rootItem())),
40 40 m_shades(new QGraphicsItemGroup(presenter->rootItem())),
41 41 m_labels(new QGraphicsItemGroup(presenter->rootItem())),
42 42 m_arrow(new QGraphicsItemGroup(presenter->rootItem())),
43 43 m_title(new QGraphicsSimpleTextItem(presenter->rootItem())),
44 44 m_min(0),
45 45 m_max(0),
46 46 m_animation(0),
47 47 m_labelPadding(5),
48 48 m_intervalAxis(intervalAxis)
49 49 {
50 50 //initial initialization
51 51 m_arrow->setZValue(ChartPresenter::AxisZValue);
52 52 m_arrow->setHandlesChildEvents(false);
53 53 m_labels->setZValue(ChartPresenter::AxisZValue);
54 54 m_shades->setZValue(ChartPresenter::ShadesZValue);
55 55 m_grid->setZValue(ChartPresenter::GridZValue);
56 56 m_title->setZValue(ChartPresenter::GridZValue);
57 57
58 58 QObject::connect(m_chartAxis->d_ptr.data(), SIGNAL(updated()), this, SLOT(handleAxisUpdated()));
59 59
60 60 QGraphicsSimpleTextItem item;
61 61 m_font = item.font();
62 62
63 63 }
64 64
65 65 ChartAxis::~ChartAxis()
66 66 {
67 67 }
68 68
69 69 void ChartAxis::setAnimation(AxisAnimation *animation)
70 70 {
71 71 m_animation = animation;
72 72 }
73 73
74 74 void ChartAxis::setLayout(QVector<qreal> &layout)
75 75 {
76 76 m_layoutVector = layout;
77 77 }
78 78
79 79 void ChartAxis::createItems(int count)
80 80 {
81 81 if (m_arrow->childItems().size() == 0)
82 82 m_arrow->addToGroup(new AxisItem(this, presenter()->rootItem()));
83 83
84 84 if (m_intervalAxis && m_grid->childItems().size() == 0) {
85 85 for (int i = 0 ; i < 2 ; i ++)
86 86 m_grid->addToGroup(new QGraphicsLineItem(presenter()->rootItem()));
87 87 }
88 88
89 89 for (int i = 0; i < count; ++i) {
90 90 m_grid->addToGroup(new QGraphicsLineItem(presenter()->rootItem()));
91 91 QGraphicsSimpleTextItem *label = new QGraphicsSimpleTextItem(presenter()->rootItem());
92 92 label->setFont(m_font);
93 93 m_labels->addToGroup(label);
94 94 m_arrow->addToGroup(new QGraphicsLineItem(presenter()->rootItem()));
95 95 if ((m_grid->childItems().size()) % 2 && m_grid->childItems().size() > 2)
96 96 m_shades->addToGroup(new QGraphicsRectItem(presenter()->rootItem()));
97 97 }
98 98 }
99 99
100 100 void ChartAxis::deleteItems(int count)
101 101 {
102 102 QList<QGraphicsItem *> lines = m_grid->childItems();
103 103 QList<QGraphicsItem *> labels = m_labels->childItems();
104 104 QList<QGraphicsItem *> shades = m_shades->childItems();
105 105 QList<QGraphicsItem *> axis = m_arrow->childItems();
106 106
107 107 for (int i = 0; i < count; ++i) {
108 108 if (lines.size() % 2 && lines.size() > 1)
109 109 delete(shades.takeLast());
110 110 delete(lines.takeLast());
111 111 delete(labels.takeLast());
112 112 delete(axis.takeLast());
113 113 }
114 114 }
115 115
116 116 void ChartAxis::updateLayout(QVector<qreal> &layout)
117 117 {
118 118 int diff = m_layoutVector.size() - layout.size();
119 119
120 120 if (diff > 0)
121 121 deleteItems(diff);
122 122 else if (diff < 0)
123 123 createItems(-diff);
124 124
125 125 if (diff < 0) handleAxisUpdated();
126 126
127 127 if (m_animation) {
128 128 switch (presenter()->state()) {
129 129 case ChartPresenter::ZoomInState:
130 130 m_animation->setAnimationType(AxisAnimation::ZoomInAnimation);
131 131 m_animation->setAnimationPoint(presenter()->statePoint());
132 132 break;
133 133 case ChartPresenter::ZoomOutState:
134 134 m_animation->setAnimationType(AxisAnimation::ZoomOutAnimation);
135 135 m_animation->setAnimationPoint(presenter()->statePoint());
136 136 break;
137 137 case ChartPresenter::ScrollUpState:
138 138 case ChartPresenter::ScrollLeftState:
139 139 m_animation->setAnimationType(AxisAnimation::MoveBackwordAnimation);
140 140 break;
141 141 case ChartPresenter::ScrollDownState:
142 142 case ChartPresenter::ScrollRightState:
143 143 m_animation->setAnimationType(AxisAnimation::MoveForwardAnimation);
144 144 break;
145 145 case ChartPresenter::ShowState:
146 146 m_animation->setAnimationType(AxisAnimation::DefaultAnimation);
147 147 break;
148 148 }
149 149 m_animation->setValues(m_layoutVector, layout);
150 150 presenter()->startAnimation(m_animation);
151 151 } else {
152 152 setLayout(layout);
153 153 updateGeometry();
154 154 }
155 155 }
156 156
157 157 void ChartAxis::setArrowOpacity(qreal opacity)
158 158 {
159 159 m_arrow->setOpacity(opacity);
160 160 }
161 161
162 162 qreal ChartAxis::arrowOpacity() const
163 163 {
164 164 return m_arrow->opacity();
165 165 }
166 166
167 167 void ChartAxis::setArrowVisibility(bool visible)
168 168 {
169 169 m_arrow->setOpacity(visible);
170 170 }
171 171
172 172 void ChartAxis::setGridOpacity(qreal opacity)
173 173 {
174 174 m_grid->setOpacity(opacity);
175 175 }
176 176
177 177 qreal ChartAxis::gridOpacity() const
178 178 {
179 179 return m_grid->opacity();
180 180 }
181 181
182 182 void ChartAxis::setGridVisibility(bool visible)
183 183 {
184 184 m_grid->setOpacity(visible);
185 185 }
186 186
187 187 void ChartAxis::setLabelsOpacity(qreal opacity)
188 188 {
189 189 m_labels->setOpacity(opacity);
190 190 }
191 191
192 192 qreal ChartAxis::labelsOpacity() const
193 193 {
194 194 return m_labels->opacity();
195 195 }
196 196
197 197 void ChartAxis::setLabelsVisibility(bool visible)
198 198 {
199 199 m_labels->setOpacity(visible);
200 200 }
201 201
202 202 void ChartAxis::setShadesOpacity(qreal opacity)
203 203 {
204 204 m_shades->setOpacity(opacity);
205 205 }
206 206
207 207 qreal ChartAxis::shadesOpacity() const
208 208 {
209 209 return m_shades->opacity();
210 210 }
211 211
212 212 void ChartAxis::setShadesVisibility(bool visible)
213 213 {
214 214 m_shades->setVisible(visible);
215 215 }
216 216
217 217 void ChartAxis::setLabelsAngle(int angle)
218 218 {
219 219 foreach (QGraphicsItem *item, m_labels->childItems())
220 220 item->setRotation(angle);
221 221
222 222 m_labelsAngle = angle;
223 223 }
224 224
225 225 void ChartAxis::setLabelsPen(const QPen &pen)
226 226 {
227 227 foreach (QGraphicsItem *item , m_labels->childItems())
228 228 static_cast<QGraphicsSimpleTextItem *>(item)->setPen(pen);
229 229 }
230 230
231 231 void ChartAxis::setLabelsBrush(const QBrush &brush)
232 232 {
233 233 foreach (QGraphicsItem *item , m_labels->childItems())
234 234 static_cast<QGraphicsSimpleTextItem *>(item)->setBrush(brush);
235 235 }
236 236
237 237 void ChartAxis::setLabelsFont(const QFont &font)
238 238 {
239 239 if (m_font != font) {
240 240 m_font = font;
241 241 foreach (QGraphicsItem *item , m_labels->childItems())
242 242 static_cast<QGraphicsSimpleTextItem *>(item)->setFont(font);
243 243 QGraphicsLayoutItem::updateGeometry();
244 244 presenter()->layout()->invalidate();
245 245 }
246 246 }
247 247
248 248 void ChartAxis::setShadesBrush(const QBrush &brush)
249 249 {
250 250 foreach (QGraphicsItem *item , m_shades->childItems())
251 251 static_cast<QGraphicsRectItem *>(item)->setBrush(brush);
252 252 }
253 253
254 254 void ChartAxis::setShadesPen(const QPen &pen)
255 255 {
256 256 foreach (QGraphicsItem *item , m_shades->childItems())
257 257 static_cast<QGraphicsRectItem *>(item)->setPen(pen);
258 258 }
259 259
260 260 void ChartAxis::setArrowPen(const QPen &pen)
261 261 {
262 262 foreach (QGraphicsItem *item , m_arrow->childItems())
263 263 static_cast<QGraphicsLineItem *>(item)->setPen(pen);
264 264 }
265 265
266 266 void ChartAxis::setGridPen(const QPen &pen)
267 267 {
268 268 foreach (QGraphicsItem *item , m_grid->childItems())
269 269 static_cast<QGraphicsLineItem *>(item)->setPen(pen);
270 270 }
271 271
272 272 void ChartAxis::setLabelPadding(int padding)
273 273 {
274 274 m_labelPadding = padding;
275 275 }
276 276
277 277 bool ChartAxis::isEmpty()
278 278 {
279 279 return m_axisRect.isEmpty() || m_gridRect.isEmpty() || qFuzzyCompare(m_min, m_max);
280 280 }
281 281
282 282 void ChartAxis::handleDomainUpdated()
283 283 {
284 284 Domain *domain = qobject_cast<Domain *>(sender());
285 285 qreal min(0);
286 286 qreal max(0);
287 287
288 288 if (m_chartAxis->orientation() == Qt::Horizontal) {
289 289 min = domain->minX();
290 290 max = domain->maxX();
291 291 } else if (m_chartAxis->orientation() == Qt::Vertical) {
292 292 min = domain->minY();
293 293 max = domain->maxY();
294 294 }
295 295
296 296 if (!qFuzzyCompare(m_min, min) || !qFuzzyCompare(m_max, max)) {
297 297 m_min = min;
298 298 m_max = max;
299 299
300 300 if (!isEmpty()) {
301 301
302 302 QVector<qreal> layout = calculateLayout();
303 303 updateLayout(layout);
304 304 QSizeF before = effectiveSizeHint(Qt::PreferredSize);
305 305 QSizeF after = sizeHint(Qt::PreferredSize);
306 306
307 307 if (before != after) {
308 308 QGraphicsLayoutItem::updateGeometry();
309 309 //we don't want to call invalidate on layout, since it will change minimum size of component,
310 310 //which we would like to avoid since it causes nasty flips when scrolling or zooming,
311 311 //instead recalculate layout and use plotArea for extra space.
312 312 presenter()->layout()->setGeometry(presenter()->layout()->geometry());
313 313 }
314 314 }
315 315 }
316 316 }
317 317
318 318 void ChartAxis::handleAxisUpdated()
319 319 {
320 320 if (isEmpty())
321 321 return;
322 322
323 323 bool visible = m_chartAxis->isVisible();
324 324
325 325 //TODO: split this into separate signal/slots ?
326 326 setArrowVisibility(visible && m_chartAxis->isLineVisible());
327 327 setGridVisibility(visible && m_chartAxis->isGridLineVisible());
328 328 setLabelsVisibility(visible && m_chartAxis->labelsVisible());
329 329 setShadesVisibility(visible && m_chartAxis->shadesVisible());
330 330 setLabelsAngle(m_chartAxis->labelsAngle());
331 331 setArrowPen(m_chartAxis->linePen());
332 332 setLabelsPen(m_chartAxis->labelsPen());
333 333 setLabelsBrush(m_chartAxis->labelsBrush());
334 334 setLabelsFont(m_chartAxis->labelsFont());
335 335 setGridPen(m_chartAxis->gridLinePen());
336 336 setShadesPen(m_chartAxis->shadesPen());
337 337 setShadesBrush(m_chartAxis->shadesBrush());
338 338 setTitleText(m_chartAxis->title());
339 339 setTitleFont(m_chartAxis->titleFont());
340 340 setTitlePen(m_chartAxis->titlePen());
341 341 setTitleBrush(m_chartAxis->titleBrush());
342 342 }
343 343
344 344 void ChartAxis::setTitleText(const QString &title)
345 345 {
346 346 if (m_titleText != title) {
347 347 m_titleText = title;
348 348 QGraphicsLayoutItem::updateGeometry();
349 349 presenter()->layout()->invalidate();
350 350 }
351 351 }
352 352
353 353 void ChartAxis::setTitlePen(const QPen &pen)
354 354 {
355 355 m_title->setPen(pen);
356 356 }
357 357
358 358 void ChartAxis::setTitleBrush(const QBrush &brush)
359 359 {
360 360 m_title->setBrush(brush);
361 361 }
362 362
363 363 void ChartAxis::setTitleFont(const QFont &font)
364 364 {
365 365 if(m_title->font() != font){
366 366 m_title->setFont(font);
367 367 QGraphicsLayoutItem::updateGeometry();
368 368 presenter()->layout()->invalidate();
369 369 }
370 370 }
371 371
372 372 QFont ChartAxis::titleFont() const
373 373 {
374 374 return m_title->font();
375 375 }
376 376
377 377 void ChartAxis::hide()
378 378 {
379 379 setArrowVisibility(false);
380 380 setGridVisibility(false);
381 381 setLabelsVisibility(false);
382 382 setShadesVisibility(false);
383 383 }
384 384
385 385 void ChartAxis::setGeometry(const QRectF &axis, const QRectF &grid)
386 386 {
387 387 m_gridRect = grid;
388 388 m_axisRect = axis;
389 389
390 390 if (isEmpty())
391 391 return;
392 392
393 393 QVector<qreal> layout = calculateLayout();
394 394 updateLayout(layout);
395 395
396 396 }
397 397
398 398 void ChartAxis::axisSelected()
399 399 {
400 400 //TODO: axis clicked;
401 401 }
402 402
403 403 Qt::Orientation ChartAxis::orientation() const
404 404 {
405 405 return m_chartAxis->orientation();
406 406 }
407 407
408 408 Qt::Alignment ChartAxis::alignment() const
409 409 {
410 410 return m_chartAxis->alignment();
411 411 }
412 412
413 413 bool ChartAxis::isVisible()
414 414 {
415 415 return m_chartAxis->isVisible();
416 416 }
417 417
418 418 void ChartAxis::setLabels(const QStringList &labels)
419 419 {
420 420 m_labelsList = labels;
421 421 }
422 422
423 423 QStringList ChartAxis::createValueLabels(int ticks) const
424 424 {
425 425 Q_ASSERT(m_max > m_min);
426 426 Q_ASSERT(ticks > 1);
427 427
428 428 QStringList labels;
429 429
430 430 int n = qMax(int(-qFloor(log10((m_max - m_min) / (ticks - 1)))), 0);
431 431 n++;
432 432
433 433 QValueAxis *axis = qobject_cast<QValueAxis *>(m_chartAxis);
434 434
435 435 QString format = axis->labelFormat();
436 436
437 437 if (format.isNull()) {
438 438 for (int i = 0; i < ticks; i++) {
439 439 qreal value = m_min + (i * (m_max - m_min) / (ticks - 1));
440 440 labels << QString::number(value, 'f', n);
441 441 }
442 442 } else {
443 443 QByteArray array = format.toLatin1();
444 444 for (int i = 0; i < ticks; i++) {
445 445 qreal value = m_min + (i * (m_max - m_min) / (ticks - 1));
446 labels << QString().sprintf(array, value);
446 if (format.contains("d")
447 || format.contains("i")
448 || format.contains("c"))
449
450 labels << QString().sprintf(array, (qint64)value);
451 else if (format.contains("u")
452 || format.contains("o")
453 || format.contains("x", Qt::CaseInsensitive))
454 labels << QString().sprintf(array, (quint64)value);
455 else
456 labels << QString().sprintf(array, value);
447 457 }
448 458 }
449 459
450 460 return labels;
451 461 }
452 462
453 463 QStringList ChartAxis::createDateTimeLabels(const QString &format, int ticks) const
454 464 {
455 465 Q_ASSERT(m_max > m_min);
456 466 Q_ASSERT(ticks > 1);
457 467 QStringList labels;
458 468 int n = qMax(int(-floor(log10((m_max - m_min) / (ticks - 1)))), 0);
459 469 n++;
460 470 for (int i = 0; i < ticks; i++) {
461 471 qreal value = m_min + (i * (m_max - m_min) / (ticks - 1));
462 472 labels << QDateTime::fromMSecsSinceEpoch(value).toString(format);
463 473 }
464 474 return labels;
465 475 }
466 476
467 477 QSizeF ChartAxis::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
468 478 {
469 479 Q_UNUSED(which);
470 480 Q_UNUSED(constraint);
471 481 return QSizeF();
472 482 }
473 483
474 484 #include "moc_chartaxis_p.cpp"
475 485
476 486 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,420 +1,422
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "qvalueaxis.h"
22 22 #include "qvalueaxis_p.h"
23 23 #include "chartvalueaxisx_p.h"
24 24 #include "chartvalueaxisy_p.h"
25 25 #include "domain_p.h"
26 26 #include "chartdataset_p.h"
27 27 #include <qmath.h>
28 28
29 29
30 30 QTCOMMERCIALCHART_BEGIN_NAMESPACE
31 31 /*!
32 32 \class QValueAxis
33 33 \brief The QValueAxis class is used for manipulating chart's axis.
34 34 \mainclass
35 35
36 36 ValueAxis can be setup to show axis line with tick marks, grid lines and shades.
37 37 Values of axis are drawn to position of ticks.
38 38
39 39 Example code on how to use QValueAxis.
40 40 \code
41 41 QChartView *chartView = new QChartView;
42 42 QLineSeries *series = new QLineSeries;
43 43 // ...
44 44 chartView->chart()->addSeries(series);
45 45
46 46 QValueAxis *axisX = new QValueAxis;
47 47 axisX->setRange(10, 20.5);
48 48 axisX->setTickCount(10);
49 49 axisX->setLabelFormat("%.2f");
50 50 chartView->chart()->setAxisX(axisX, series);
51 51 \endcode
52 52 */
53 53
54 54 /*!
55 55 \qmlclass ValueAxis QValueAxis
56 56 \inherits AbstractAxis
57 57 \brief The ValueAxis element is used for manipulating chart's axes
58 58
59 59 ValueAxis can be setup to show axis line with tick marks, grid lines and shades.
60 60 Values of axis are drawn to position of ticks
61 61
62 62 To access Axes you can use ChartView API. For example:
63 63 \code
64 64 ChartView {
65 65 ValueAxis {
66 66 id: xAxis
67 67 min: 0
68 68 max: 10
69 69 }
70 70 // Add a few series...
71 71 }
72 72 \endcode
73 73 */
74 74
75 75 /*!
76 76 \property QValueAxis::min
77 77 Defines the minimum value on the axis.
78 78 When setting this property the max is adjusted if necessary, to ensure that the range remains valid.
79 79 */
80 80 /*!
81 81 \qmlproperty real ValueAxis::min
82 82 Defines the minimum value on the axis.
83 83 When setting this property the max is adjusted if necessary, to ensure that the range remains valid.
84 84 */
85 85
86 86 /*!
87 87 \property QValueAxis::max
88 88 Defines the maximum value on the axis.
89 89 When setting this property the min is adjusted if necessary, to ensure that the range remains valid.
90 90 */
91 91 /*!
92 92 \qmlproperty real ValueAxis::max
93 93 Defines the maximum value on the axis.
94 94 When setting this property the min is adjusted if necessary, to ensure that the range remains valid.
95 95 */
96 96
97 97 /*!
98 98 \property QValueAxis::labelFormat
99 99 Defines the label format for the axis.
100 See QString::sprintf() for the details.
100 Supported specifiers are: d, i, o, x, X, f, F, e, E, g, G, c
101 See QString::sprintf() for additional details.
101 102 */
102 103 /*!
103 104 \qmlproperty real ValueAxis::labelFormat
104 105 Defines the label format for the axis.
105 See QString::sprintf() for the details.
106 Supported specifiers are: d, i, o, x, X, f, F, e, E, g, G, c
107 See QString::sprintf() for additional details.
106 108 */
107 109
108 110 /*!
109 111 \fn void QValueAxis::minChanged(qreal min)
110 112 Axis emits signal when \a min of axis has changed.
111 113 */
112 114 /*!
113 115 \qmlsignal ValueAxis::onMinChanged(real min)
114 116 Axis emits signal when \a min of axis has changed.
115 117 */
116 118
117 119 /*!
118 120 \fn void QValueAxis::maxChanged(qreal max)
119 121 Axis emits signal when \a max of axis has changed.
120 122 */
121 123 /*!
122 124 \qmlsignal ValueAxis::onMaxChanged(real max)
123 125 Axis emits signal when \a max of axis has changed.
124 126 */
125 127
126 128 /*!
127 129 \fn void QValueAxis::rangeChanged(qreal min, qreal max)
128 130 Axis emits signal when \a min or \a max of axis has changed.
129 131 */
130 132
131 133 /*!
132 134 \property QValueAxis::tickCount
133 135 The number of tick marks for the axis.
134 136 */
135 137
136 138 /*!
137 139 \qmlproperty int ValueAxis::tickCount
138 140 The number of tick marks for the axis.
139 141 */
140 142
141 143 /*!
142 144 \property QValueAxis::niceNumbersEnabled
143 145 Whether the nice numbers algorithm is enabled or not for the axis.
144 146 */
145 147
146 148 /*!
147 149 \qmlproperty bool ValueAxis::niceNumbersEnabled
148 150 Whether the nice numbers algorithm is enabled or not for the axis.
149 151 */
150 152
151 153 /*!
152 154 Constructs an axis object which is a child of \a parent.
153 155 */
154 156 QValueAxis::QValueAxis(QObject *parent) :
155 157 QAbstractAxis(*new QValueAxisPrivate(this), parent)
156 158 {
157 159
158 160 }
159 161
160 162 /*!
161 163 \internal
162 164 */
163 165 QValueAxis::QValueAxis(QValueAxisPrivate &d, QObject *parent)
164 166 : QAbstractAxis(d, parent)
165 167 {
166 168
167 169 }
168 170
169 171 /*!
170 172 Destroys the object
171 173 */
172 174 QValueAxis::~QValueAxis()
173 175 {
174 176 Q_D(QValueAxis);
175 177 if (d->m_dataset)
176 178 d->m_dataset->removeAxis(this);
177 179 }
178 180
179 181 void QValueAxis::setMin(qreal min)
180 182 {
181 183 Q_D(QValueAxis);
182 184 setRange(min, qMax(d->m_max, min));
183 185 }
184 186
185 187 qreal QValueAxis::min() const
186 188 {
187 189 Q_D(const QValueAxis);
188 190 return d->m_min;
189 191 }
190 192
191 193 void QValueAxis::setMax(qreal max)
192 194 {
193 195 Q_D(QValueAxis);
194 196 setRange(qMin(d->m_min, max), max);
195 197 }
196 198
197 199 qreal QValueAxis::max() const
198 200 {
199 201 Q_D(const QValueAxis);
200 202 return d->m_max;
201 203 }
202 204
203 205 /*!
204 206 Sets range from \a min to \a max on the axis.
205 207 If min is greater than max then this function returns without making any changes.
206 208 */
207 209 void QValueAxis::setRange(qreal min, qreal max)
208 210 {
209 211 Q_D(QValueAxis);
210 212 bool changed = false;
211 213
212 214 if (min > max)
213 215 return;
214 216
215 217 if (d->m_niceNumbers) {
216 218 int ticks = d->m_tickCount;
217 219 d->looseNiceNumbers(min, max, ticks);
218 220 if (ticks != d->m_tickCount)
219 221 setTickCount(ticks);
220 222 }
221 223
222 224 if (!qFuzzyCompare(d->m_min, min)) {
223 225 d->m_min = min;
224 226 changed = true;
225 227 emit minChanged(min);
226 228 }
227 229
228 230 if (!qFuzzyCompare(d->m_max, max)) {
229 231 d->m_max = max;
230 232 changed = true;
231 233 emit maxChanged(max);
232 234 }
233 235
234 236 if (changed) {
235 237 emit rangeChanged(min, max);
236 238 d->emitUpdated();
237 239 }
238 240 }
239 241
240 242 /*!
241 243 Sets \a count for ticks on the axis.
242 244 */
243 245 void QValueAxis::setTickCount(int count)
244 246 {
245 247 Q_D(QValueAxis);
246 248 if (d->m_tickCount != count && count >= 2) {
247 249 d->m_tickCount = count;
248 250 d->emitUpdated();
249 251 }
250 252 }
251 253
252 254 /*!
253 255 \fn int QValueAxis::tickCount() const
254 256 Return number of ticks on the axis
255 257 */
256 258 int QValueAxis::tickCount() const
257 259 {
258 260 Q_D(const QValueAxis);
259 261 return d->m_tickCount;
260 262 }
261 263
262 264 void QValueAxis::setNiceNumbersEnabled(bool enable)
263 265 {
264 266 Q_D(QValueAxis);
265 267 if (d->m_niceNumbers != enable) {
266 268 d->m_niceNumbers = enable;
267 269 if (enable && !qFuzzyCompare(d->m_max, d->m_min))
268 270 setRange(d->m_min, d->m_max);
269 271 }
270 272 }
271 273
272 274 bool QValueAxis::niceNumbersEnabled() const
273 275 {
274 276 Q_D(const QValueAxis);
275 277 return d->m_niceNumbers;
276 278 }
277 279
278 280 void QValueAxis::setLabelFormat(const QString &format)
279 281 {
280 282 Q_D(QValueAxis);
281 283 d->m_format = format;
282 284 }
283 285
284 286 QString QValueAxis::labelFormat() const
285 287 {
286 288 Q_D(const QValueAxis);
287 289 return d->m_format;
288 290 }
289 291
290 292 /*!
291 293 Returns the type of the axis
292 294 */
293 295 QAbstractAxis::AxisType QValueAxis::type() const
294 296 {
295 297 return AxisTypeValue;
296 298 }
297 299
298 300 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
299 301
300 302 QValueAxisPrivate::QValueAxisPrivate(QValueAxis *q)
301 303 : QAbstractAxisPrivate(q),
302 304 m_min(0),
303 305 m_max(0),
304 306 m_tickCount(5),
305 307 m_niceNumbers(false),
306 308 m_format(QString::null)
307 309 {
308 310
309 311 }
310 312
311 313 QValueAxisPrivate::~QValueAxisPrivate()
312 314 {
313 315
314 316 }
315 317
316 318 void QValueAxisPrivate::handleDomainUpdated()
317 319 {
318 320 Q_Q(QValueAxis);
319 321 Domain *domain = qobject_cast<Domain *>(sender());
320 322 Q_ASSERT(domain);
321 323
322 324 if (orientation() == Qt::Horizontal)
323 325 q->setRange(domain->minX(), domain->maxX());
324 326 else if (orientation() == Qt::Vertical)
325 327 q->setRange(domain->minY(), domain->maxY());
326 328 }
327 329
328 330
329 331 void QValueAxisPrivate::setMin(const QVariant &min)
330 332 {
331 333 Q_Q(QValueAxis);
332 334 bool ok;
333 335 qreal value = min.toReal(&ok);
334 336 if (ok)
335 337 q->setMin(value);
336 338 }
337 339
338 340 void QValueAxisPrivate::setMax(const QVariant &max)
339 341 {
340 342
341 343 Q_Q(QValueAxis);
342 344 bool ok;
343 345 qreal value = max.toReal(&ok);
344 346 if (ok)
345 347 q->setMax(value);
346 348 }
347 349
348 350 void QValueAxisPrivate::setRange(const QVariant &min, const QVariant &max)
349 351 {
350 352 Q_Q(QValueAxis);
351 353 bool ok1;
352 354 bool ok2;
353 355 qreal value1 = min.toReal(&ok1);
354 356 qreal value2 = max.toReal(&ok2);
355 357 if (ok1 && ok2)
356 358 q->setRange(value1, value2);
357 359 }
358 360
359 361 ChartAxis *QValueAxisPrivate::createGraphics(ChartPresenter *presenter)
360 362 {
361 363 Q_Q(QValueAxis);
362 364 if (m_orientation == Qt::Vertical)
363 365 return new ChartValueAxisY(q, presenter);
364 366 return new ChartValueAxisX(q, presenter);
365 367 }
366 368
367 369 void QValueAxisPrivate::intializeDomain(Domain *domain)
368 370 {
369 371 Q_Q(QValueAxis);
370 372 if (qFuzzyCompare(m_max, m_min)) {
371 373 if (m_orientation == Qt::Vertical)
372 374 q->setRange(domain->minY(), domain->maxY());
373 375 else
374 376 q->setRange(domain->minX(), domain->maxX());
375 377 } else {
376 378 if (m_orientation == Qt::Vertical)
377 379 domain->setRangeY(m_min, m_max);
378 380 else
379 381 domain->setRangeX(m_min, m_max);
380 382 }
381 383 }
382 384
383 385 //algorithm defined by Paul S.Heckbert GraphicalGems I
384 386
385 387 void QValueAxisPrivate::looseNiceNumbers(qreal &min, qreal &max, int &ticksCount) const
386 388 {
387 389 qreal range = niceNumber(max - min, true); //range with ceiling
388 390 qreal step = niceNumber(range / (ticksCount - 1), false);
389 391 min = qFloor(min / step);
390 392 max = qCeil(max / step);
391 393 ticksCount = int(max - min) + 1;
392 394 min *= step;
393 395 max *= step;
394 396 }
395 397
396 398 //nice numbers can be expressed as form of 1*10^n, 2* 10^n or 5*10^n
397 399
398 400 qreal QValueAxisPrivate::niceNumber(qreal x, bool ceiling) const
399 401 {
400 402 qreal z = qPow(10, qFloor(log10(x))); //find corresponding number of the form of 10^n than is smaller than x
401 403 qreal q = x / z; //q<10 && q>=1;
402 404
403 405 if (ceiling) {
404 406 if (q <= 1.0) q = 1;
405 407 else if (q <= 2.0) q = 2;
406 408 else if (q <= 5.0) q = 5;
407 409 else q = 10;
408 410 } else {
409 411 if (q < 1.5) q = 1;
410 412 else if (q < 3.0) q = 2;
411 413 else if (q < 7.0) q = 5;
412 414 else q = 10;
413 415 }
414 416 return q * z;
415 417 }
416 418
417 419 #include "moc_qvalueaxis.cpp"
418 420 #include "moc_qvalueaxis_p.cpp"
419 421
420 422 QTCOMMERCIALCHART_END_NAMESPACE
General Comments 0
You need to be logged in to leave comments. Login now