##// END OF EJS Templates
Makes theming axis title aware
Michal Klocek -
r2153:cd956b4e0b4d
parent child
Show More
@@ -1,122 +1,126
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 "charts.h"
22 22 #include "qchart.h"
23 23 #include "qlineseries.h"
24 24
25 25 class FontChart: public Chart
26 26 {
27 27 public:
28 28 FontChart(int fontSize): m_fontSize(fontSize) {};
29 29 QString name() { return QObject::tr("Font") + " " + QString::number(m_fontSize); }
30 30 QString category() { return QObject::tr("Font"); }
31 31 QString subCategory() { return QString::null; }
32 32
33 33 QChart *createChart(const DataTable &table)
34 34 {
35 35 QChart *chart = new QChart();
36 36 chart->setTitle("Font size " + QString::number(m_fontSize));
37 37 QString name("Series ");
38 38 int nameIndex = 0;
39 39 foreach (DataList list, table) {
40 40 QLineSeries *series = new QLineSeries(chart);
41 41 foreach (Data data, list)
42 42 series->append(data.first);
43 43 series->setName(name + QString::number(nameIndex));
44 44 nameIndex++;
45 45 chart->addSeries(series);
46 46 }
47 47 chart->createDefaultAxes();
48 48 QFont font;
49 49 font.setPixelSize(m_fontSize);
50 50 chart->setTitleFont(font);
51 51 chart->axisX()->setLabelsFont(font);
52 52 chart->axisY()->setLabelsFont(font);
53 chart->axisX()->setTitle("Axis X");
54 chart->axisY()->setTitle("Axis Y");
55 chart->axisX()->setTitleFont(font);
56 chart->axisY()->setTitleFont(font);
53 57 return chart;
54 58 }
55 59
56 60 private:
57 61 int m_fontSize;
58 62 };
59 63
60 64 class FontChart6: public FontChart
61 65 {
62 66 public:
63 67 FontChart6(): FontChart(6) {};
64 68 };
65 69
66 70 class FontChart8: public FontChart
67 71 {
68 72 public:
69 73 FontChart8(): FontChart(8) {};
70 74 };
71 75
72 76 class FontChart10: public FontChart
73 77 {
74 78 public:
75 79 FontChart10(): FontChart(10) {};
76 80 };
77 81
78 82 class FontChart14: public FontChart
79 83 {
80 84 public:
81 85 FontChart14(): FontChart(14) {};
82 86 };
83 87
84 88 class FontChart18: public FontChart
85 89 {
86 90 public:
87 91 FontChart18(): FontChart(18) {};
88 92 };
89 93
90 94 class FontChart20: public FontChart
91 95 {
92 96 public:
93 97 FontChart20(): FontChart(20) {};
94 98 };
95 99
96 100 class FontChart24: public FontChart
97 101 {
98 102 public:
99 103 FontChart24(): FontChart(24) {};
100 104 };
101 105
102 106 class FontChart28: public FontChart
103 107 {
104 108 public:
105 109 FontChart28(): FontChart(28) {};
106 110 };
107 111
108 112 class FontChart32: public FontChart
109 113 {
110 114 public:
111 115 FontChart32(): FontChart(32) {};
112 116 };
113 117
114 118 DECLARE_CHART(FontChart6);
115 119 DECLARE_CHART(FontChart8);
116 120 DECLARE_CHART(FontChart10);
117 121 DECLARE_CHART(FontChart14);
118 122 DECLARE_CHART(FontChart18);
119 123 DECLARE_CHART(FontChart20);
120 124 DECLARE_CHART(FontChart24);
121 125 DECLARE_CHART(FontChart28);
122 126 DECLARE_CHART(FontChart32);
@@ -1,449 +1,474
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->children().size() == 0)
82 82 m_arrow->addToGroup(new AxisItem(this, presenter()->rootItem()));
83 83
84 84 if (m_intervalAxis && m_grid->children().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 m_labels->addToGroup(new QGraphicsSimpleTextItem(presenter()->rootItem()));
92 92 m_arrow->addToGroup(new QGraphicsLineItem(presenter()->rootItem()));
93 93 if ((m_grid->childItems().size()) % 2 && m_grid->childItems().size() > 2)
94 94 m_shades->addToGroup(new QGraphicsRectItem(presenter()->rootItem()));
95 95 }
96 96 }
97 97
98 98 void ChartAxis::deleteItems(int count)
99 99 {
100 100 QList<QGraphicsItem *> lines = m_grid->childItems();
101 101 QList<QGraphicsItem *> labels = m_labels->childItems();
102 102 QList<QGraphicsItem *> shades = m_shades->childItems();
103 103 QList<QGraphicsItem *> axis = m_arrow->childItems();
104 104
105 105 for (int i = 0; i < count; ++i) {
106 106 if (lines.size() % 2 && lines.size() > 1)
107 107 delete(shades.takeLast());
108 108 delete(lines.takeLast());
109 109 delete(labels.takeLast());
110 110 delete(axis.takeLast());
111 111 }
112 112 }
113 113
114 114 void ChartAxis::updateLayout(QVector<qreal> &layout)
115 115 {
116 116 int diff = m_layoutVector.size() - layout.size();
117 117
118 118 if (diff > 0)
119 119 deleteItems(diff);
120 120 else if (diff < 0)
121 121 createItems(-diff);
122 122
123 123 if (diff < 0) handleAxisUpdated();
124 124
125 125 if (m_animation) {
126 126 switch (presenter()->state()) {
127 127 case ChartPresenter::ZoomInState:
128 128 m_animation->setAnimationType(AxisAnimation::ZoomInAnimation);
129 129 m_animation->setAnimationPoint(presenter()->statePoint());
130 130 break;
131 131 case ChartPresenter::ZoomOutState:
132 132 m_animation->setAnimationType(AxisAnimation::ZoomOutAnimation);
133 133 m_animation->setAnimationPoint(presenter()->statePoint());
134 134 break;
135 135 case ChartPresenter::ScrollUpState:
136 136 case ChartPresenter::ScrollLeftState:
137 137 m_animation->setAnimationType(AxisAnimation::MoveBackwordAnimation);
138 138 break;
139 139 case ChartPresenter::ScrollDownState:
140 140 case ChartPresenter::ScrollRightState:
141 141 m_animation->setAnimationType(AxisAnimation::MoveForwardAnimation);
142 142 break;
143 143 case ChartPresenter::ShowState:
144 144 m_animation->setAnimationType(AxisAnimation::DefaultAnimation);
145 145 break;
146 146 }
147 147 m_animation->setValues(m_layoutVector, layout);
148 148 presenter()->startAnimation(m_animation);
149 149 } else {
150 150 setLayout(layout);
151 151 updateGeometry();
152 152 }
153 153 }
154 154
155 155 void ChartAxis::setArrowOpacity(qreal opacity)
156 156 {
157 157 m_arrow->setOpacity(opacity);
158 158 }
159 159
160 160 qreal ChartAxis::arrowOpacity() const
161 161 {
162 162 return m_arrow->opacity();
163 163 }
164 164
165 165 void ChartAxis::setArrowVisibility(bool visible)
166 166 {
167 167 m_arrow->setOpacity(visible);
168 168 }
169 169
170 170 void ChartAxis::setGridOpacity(qreal opacity)
171 171 {
172 172 m_grid->setOpacity(opacity);
173 173 }
174 174
175 175 qreal ChartAxis::gridOpacity() const
176 176 {
177 177 return m_grid->opacity();
178 178 }
179 179
180 180 void ChartAxis::setGridVisibility(bool visible)
181 181 {
182 182 m_grid->setOpacity(visible);
183 183 }
184 184
185 185 void ChartAxis::setLabelsOpacity(qreal opacity)
186 186 {
187 187 m_labels->setOpacity(opacity);
188 188 }
189 189
190 190 qreal ChartAxis::labelsOpacity() const
191 191 {
192 192 return m_labels->opacity();
193 193 }
194 194
195 195 void ChartAxis::setLabelsVisibility(bool visible)
196 196 {
197 197 m_labels->setOpacity(visible);
198 198 }
199 199
200 200 void ChartAxis::setShadesOpacity(qreal opacity)
201 201 {
202 202 m_shades->setOpacity(opacity);
203 203 }
204 204
205 205 qreal ChartAxis::shadesOpacity() const
206 206 {
207 207 return m_shades->opacity();
208 208 }
209 209
210 210 void ChartAxis::setShadesVisibility(bool visible)
211 211 {
212 212 m_shades->setVisible(visible);
213 213 }
214 214
215 215 void ChartAxis::setLabelsAngle(int angle)
216 216 {
217 217 foreach (QGraphicsItem *item, m_labels->childItems())
218 218 item->setRotation(angle);
219 219
220 220 m_labelsAngle = angle;
221 221 }
222 222
223 223 void ChartAxis::setLabelsPen(const QPen &pen)
224 224 {
225 225 foreach (QGraphicsItem *item , m_labels->childItems())
226 226 static_cast<QGraphicsSimpleTextItem *>(item)->setPen(pen);
227 227 }
228 228
229 229 void ChartAxis::setLabelsBrush(const QBrush &brush)
230 230 {
231 231 foreach (QGraphicsItem *item , m_labels->childItems())
232 232 static_cast<QGraphicsSimpleTextItem *>(item)->setBrush(brush);
233 233 }
234 234
235 235 void ChartAxis::setLabelsFont(const QFont &font)
236 236 {
237 foreach (QGraphicsItem *item , m_labels->childItems())
238 static_cast<QGraphicsSimpleTextItem *>(item)->setFont(font);
239
240 237 if (m_font != font) {
241 238 m_font = font;
242 239 foreach (QGraphicsItem *item , m_labels->childItems())
243 240 static_cast<QGraphicsSimpleTextItem *>(item)->setFont(font);
244 241 QGraphicsLayoutItem::updateGeometry();
245 242 presenter()->layout()->invalidate();
246 243 }
247 244 }
248 245
249 246 void ChartAxis::setShadesBrush(const QBrush &brush)
250 247 {
251 248 foreach (QGraphicsItem *item , m_shades->childItems())
252 249 static_cast<QGraphicsRectItem *>(item)->setBrush(brush);
253 250 }
254 251
255 252 void ChartAxis::setShadesPen(const QPen &pen)
256 253 {
257 254 foreach (QGraphicsItem *item , m_shades->childItems())
258 255 static_cast<QGraphicsRectItem *>(item)->setPen(pen);
259 256 }
260 257
261 258 void ChartAxis::setArrowPen(const QPen &pen)
262 259 {
263 260 foreach (QGraphicsItem *item , m_arrow->childItems())
264 261 static_cast<QGraphicsLineItem *>(item)->setPen(pen);
265 262 }
266 263
267 264 void ChartAxis::setGridPen(const QPen &pen)
268 265 {
269 266 foreach (QGraphicsItem *item , m_grid->childItems())
270 267 static_cast<QGraphicsLineItem *>(item)->setPen(pen);
271 268 }
272 269
273 270 void ChartAxis::setLabelPadding(int padding)
274 271 {
275 272 m_labelPadding = padding;
276 273 }
277 274
278 275 bool ChartAxis::isEmpty()
279 276 {
280 277 return m_axisRect.isEmpty() || m_gridRect.isEmpty() || qFuzzyIsNull(m_min - m_max);
281 278 }
282 279
283 280 void ChartAxis::handleDomainUpdated()
284 281 {
285 282 Domain *domain = qobject_cast<Domain *>(sender());
286 283 qreal min(0);
287 284 qreal max(0);
288 285
289 286 if (m_chartAxis->orientation() == Qt::Horizontal) {
290 287 min = domain->minX();
291 288 max = domain->maxX();
292 289 } else if (m_chartAxis->orientation() == Qt::Vertical) {
293 290 min = domain->minY();
294 291 max = domain->maxY();
295 292 }
296 293
297 294 if (!qFuzzyIsNull(m_min - min) || !qFuzzyIsNull(m_max - max)) {
298 295 m_min = min;
299 296 m_max = max;
300 297
301 298 if (!isEmpty()) {
302 299
303 300 QVector<qreal> layout = calculateLayout();
304 301 updateLayout(layout);
305 302 QSizeF before = effectiveSizeHint(Qt::PreferredSize);
306 303 QSizeF after = sizeHint(Qt::PreferredSize);
307 304
308 305 if (before != after) {
309 306 QGraphicsLayoutItem::updateGeometry();
310 307 //we don't want to call invalidate on layout, since it will change minimum size of component,
311 308 //which we would like to avoid since it causes nasty flips when scrolling or zooming,
312 309 //instead recalculate layout and use plotArea for extra space.
313 310 presenter()->layout()->setGeometry(presenter()->layout()->geometry());
314 311 }
315 312 }
316 313 }
317 314 }
318 315
319 316 void ChartAxis::handleAxisUpdated()
320 317 {
321 318 if (isEmpty())
322 319 return;
323 320
324 321 bool visible = m_chartAxis->isVisible();
325 322
323 //TODO: split this into separate signal/slots ?
326 324 setArrowVisibility(visible && m_chartAxis->isLineVisible());
327 325 setGridVisibility(visible && m_chartAxis->isGridLineVisible());
328 326 setLabelsVisibility(visible && m_chartAxis->labelsVisible());
329 327 setShadesVisibility(visible && m_chartAxis->shadesVisible());
330 328 setLabelsAngle(m_chartAxis->labelsAngle());
331 329 setArrowPen(m_chartAxis->linePen());
332 330 setLabelsPen(m_chartAxis->labelsPen());
333 331 setLabelsBrush(m_chartAxis->labelsBrush());
334 332 setLabelsFont(m_chartAxis->labelsFont());
335 333 setGridPen(m_chartAxis->gridLinePen());
336 334 setShadesPen(m_chartAxis->shadesPen());
337 335 setShadesBrush(m_chartAxis->shadesBrush());
338 336 setTitleText(m_chartAxis->title());
337 setTitleFont(m_chartAxis->titleFont());
338 setTitlePen(m_chartAxis->titlePen());
339 setTitleBrush(m_chartAxis->titleBrush());
339 340 }
340 341
341 342 void ChartAxis::setTitleText(const QString &title)
342 343 {
343 344 if (m_titleText != title) {
344 345 m_titleText = title;
345 346 QGraphicsLayoutItem::updateGeometry();
346 347 presenter()->layout()->invalidate();
347 348 }
348 349 }
349 350
351 void ChartAxis::setTitlePen(const QPen &pen)
352 {
353 m_title->setPen(pen);
354 }
355
356 void ChartAxis::setTitleBrush(const QBrush &brush)
357 {
358 m_title->setBrush(brush);
359 }
360
361 void ChartAxis::setTitleFont(const QFont &font)
362 {
363 if(m_title->font() != font){
364 m_title->setFont(font);
365 QGraphicsLayoutItem::updateGeometry();
366 presenter()->layout()->invalidate();
367 }
368 }
369
370 QFont ChartAxis::titleFont() const
371 {
372 return m_title->font();
373 }
374
350 375 void ChartAxis::hide()
351 376 {
352 377 setArrowVisibility(false);
353 378 setGridVisibility(false);
354 379 setLabelsVisibility(false);
355 380 setShadesVisibility(false);
356 381 }
357 382
358 383 void ChartAxis::setGeometry(const QRectF &axis, const QRectF &grid)
359 384 {
360 385 m_gridRect = grid;
361 386 m_axisRect = axis;
362 387
363 388 if (isEmpty())
364 389 return;
365 390
366 391 QVector<qreal> layout = calculateLayout();
367 392 updateLayout(layout);
368 393
369 394 }
370 395
371 396 void ChartAxis::axisSelected()
372 397 {
373 398 //TODO: axis clicked;
374 399 }
375 400
376 401 Qt::Orientation ChartAxis::orientation() const
377 402 {
378 403 return m_chartAxis->orientation();
379 404 }
380 405
381 406 Qt::Alignment ChartAxis::alignment() const
382 407 {
383 408 return m_chartAxis->alignment();
384 409 }
385 410
386 411 bool ChartAxis::isVisible()
387 412 {
388 413 return m_chartAxis->isVisible();
389 414 }
390 415
391 416 void ChartAxis::setLabels(const QStringList &labels)
392 417 {
393 418 m_labelsList = labels;
394 419 }
395 420
396 421 QStringList ChartAxis::createValueLabels(int ticks) const
397 422 {
398 423 Q_ASSERT(m_max > m_min);
399 424 Q_ASSERT(ticks > 1);
400 425
401 426 QStringList labels;
402 427
403 428 int n = qMax(int(-qFloor(log10((m_max - m_min) / (ticks - 1)))), 0);
404 429 n++;
405 430
406 431 QValueAxis *axis = qobject_cast<QValueAxis *>(m_chartAxis);
407 432
408 433 QString format = axis->labelFormat();
409 434
410 435 if (format.isNull()) {
411 436 for (int i = 0; i < ticks; i++) {
412 437 qreal value = m_min + (i * (m_max - m_min) / (ticks - 1));
413 438 labels << QString::number(value, 'f', n);
414 439 }
415 440 } else {
416 441 QByteArray array = format.toAscii();
417 442 for (int i = 0; i < ticks; i++) {
418 443 qreal value = m_min + (i * (m_max - m_min) / (ticks - 1));
419 444 labels << QString().sprintf(array, value);
420 445 }
421 446 }
422 447
423 448 return labels;
424 449 }
425 450
426 451 QStringList ChartAxis::createDateTimeLabels(const QString &format, int ticks) const
427 452 {
428 453 Q_ASSERT(m_max > m_min);
429 454 Q_ASSERT(ticks > 1);
430 455 QStringList labels;
431 456 int n = qMax(int(-floor(log10((m_max - m_min) / (ticks - 1)))), 0);
432 457 n++;
433 458 for (int i = 0; i < ticks; i++) {
434 459 qreal value = m_min + (i * (m_max - m_min) / (ticks - 1));
435 460 labels << QDateTime::fromMSecsSinceEpoch(value).toString(format);
436 461 }
437 462 return labels;
438 463 }
439 464
440 465 QSizeF ChartAxis::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
441 466 {
442 467 Q_UNUSED(which);
443 468 Q_UNUSED(constraint);
444 469 return QSizeF();
445 470 }
446 471
447 472 #include "moc_chartaxis_p.cpp"
448 473
449 474 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,201 +1,200
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 // W A R N I N G
22 22 // -------------
23 23 //
24 24 // This file is not part of the QtCommercial Chart API. It exists purely as an
25 25 // implementation detail. This header file may change from version to
26 26 // version without notice, or even be removed.
27 27 //
28 28 // We mean it.
29 29
30 30 #ifndef CHARTAXIS_H
31 31 #define CHARTAXIS_H
32 32
33 33 #include "qchartglobal.h"
34 34 #include "chartelement_p.h"
35 35 #include "axisanimation_p.h"
36 36 #include <QGraphicsItem>
37 37 #include <QGraphicsLayoutItem>
38 38 #include <QFont>
39 39
40 40 QTCOMMERCIALCHART_BEGIN_NAMESPACE
41 41
42 42 class QAbstractAxis;
43 43 class ChartPresenter;
44 44
45 45 class ChartAxis : public ChartElement, public QGraphicsLayoutItem
46 46 {
47 47 Q_OBJECT
48 48 Q_INTERFACES(QGraphicsLayoutItem)
49 49 public:
50 50
51 51 ChartAxis(QAbstractAxis *axis, ChartPresenter *presenter, bool intervalAxis = false);
52 52 ~ChartAxis();
53 53
54 54 QAbstractAxis* axis() const { return m_chartAxis; }
55 55
56 56 void setArrowOpacity(qreal opacity);
57 57 qreal arrowOpacity() const;
58 58 void setArrowVisibility(bool visible);
59 59
60 60 void setGridOpacity(qreal opacity);
61 61 qreal gridOpacity() const;
62 62 void setGridVisibility(bool visible);
63 63
64 64 void setLabelsOpacity(qreal opacity);
65 65 qreal labelsOpacity() const;
66 66 void setLabelsVisibility(bool visible);
67 67
68 68 void setShadesOpacity(qreal opacity);
69 69 qreal shadesOpacity() const;
70 70 void setShadesVisibility(bool visible);
71 71
72 72 void setLabelsAngle(int angle);
73 73 int labelsAngle()const { return m_labelsAngle; }
74 74
75 75 void setShadesBrush(const QBrush &brush);
76 76 void setShadesPen(const QPen &pen);
77 77
78 78 void setArrowPen(const QPen &pen);
79 79 void setGridPen(const QPen &pen);
80 80
81 81 void setLabelsPen(const QPen &pen);
82 82 void setLabelsBrush(const QBrush &brush);
83 83 void setLabelsFont(const QFont &font);
84 84 void setLabelPadding(int padding);
85 85 int labelPadding() const { return m_labelPadding;};
86 86
87 87 void setTitlePen(const QPen &pen);
88 88 void setTitleBrush(const QBrush &brush);
89 89 void setTitleFont(const QFont &font);
90 QFont titleFont() const { return m_titleFont; };
90 QFont titleFont() const;
91 91 void setTitleText(const QString &title);
92 92 QString titleText() const {return m_titleText; };
93 93
94 94 void setLayout(QVector<qreal> &layout);
95 95 QVector<qreal> layout() const { return m_layoutVector; }
96 96
97 97 void setAnimation(AxisAnimation *animation);
98 98 ChartAnimation *animation() const { return m_animation; };
99 99
100 100 Qt::Orientation orientation() const;
101 101 Qt::Alignment alignment() const;
102 102
103 103 bool isVisible();
104 104 void hide();
105 105
106 106 void setGeometry(const QRectF &axis, const QRectF &grid);
107 107 QRectF axisGeometry() const { return m_axisRect; }
108 108 QRectF gridGeometry() const { return m_gridRect; }
109 109
110 110 void setLabels(const QStringList &labels);
111 111 QStringList labels() const { return m_labelsList; }
112 112
113 113 //this flag indicates that axis is used to show intervals it means labels are in between ticks
114 114 bool intervalAxis() const { return m_intervalAxis; }
115 115
116 116 virtual QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const;
117 117
118 118 protected:
119 119 void setGeometry(const QRectF &size) { Q_UNUSED(size);};
120 120 virtual void updateGeometry() = 0;
121 121 virtual QVector<qreal> calculateLayout() const = 0;
122 122
123 123 QList<QGraphicsItem *> lineItems() { return m_grid->childItems(); };
124 124 QList<QGraphicsItem *> labelItems() { return m_labels->childItems();};
125 125 QList<QGraphicsItem *> shadeItems() { return m_shades->childItems();};
126 126 QList<QGraphicsItem *> arrowItems() { return m_arrow->childItems();};
127 127 QGraphicsSimpleTextItem* titleItem() const { return m_title.data();}
128 128
129 129 QFont font() const { return m_font; }
130 130 qreal min() const {return m_min; }
131 131 qreal max() const {return m_max; }
132 132 QStringList createValueLabels(int ticks) const;
133 133 QStringList createDateTimeLabels(const QString &format, int ticks) const;
134 134
135 135 public Q_SLOTS:
136 136 virtual void handleAxisUpdated();
137 137 virtual void handleDomainUpdated();
138 138
139 139 private:
140 140 inline bool isEmpty();
141 141 void createItems(int count);
142 142 void deleteItems(int count);
143 143 void updateLayout(QVector<qreal> &layout);
144 144 void axisSelected();
145 145
146 146 private:
147 147 QAbstractAxis *m_chartAxis;
148 148 int m_labelsAngle;
149 149 QRectF m_axisRect;
150 150 QRectF m_gridRect;
151 151 QScopedPointer<QGraphicsItemGroup> m_grid;
152 152 QScopedPointer<QGraphicsItemGroup> m_shades;
153 153 QScopedPointer<QGraphicsItemGroup> m_labels;
154 154 QScopedPointer<QGraphicsItemGroup> m_arrow;
155 155 QScopedPointer<QGraphicsSimpleTextItem> m_title;
156 156 QVector<qreal> m_layoutVector;
157 157 qreal m_min;
158 158 qreal m_max;
159 159 AxisAnimation *m_animation;
160 160 QFont m_font;
161 QFont m_titleFont;
162 161 QString m_titleText;
163 162 int m_labelPadding;
164 163 QStringList m_labelsList;
165 164 bool m_intervalAxis;
166 165
167 166 friend class AxisAnimation;
168 167 friend class AxisItem;
169 168
170 169 };
171 170
172 171 class AxisItem: public QGraphicsLineItem
173 172 {
174 173
175 174 public:
176 175 explicit AxisItem(ChartAxis *axis, QGraphicsItem *parent = 0) : QGraphicsLineItem(parent), m_axis(axis) {}
177 176
178 177 protected:
179 178 void mousePressEvent(QGraphicsSceneMouseEvent *event) {
180 179 Q_UNUSED(event)
181 180 m_axis->axisSelected();
182 181 }
183 182
184 183 QRectF boundingRect() const {
185 184 return shape().boundingRect();
186 185 }
187 186
188 187 QPainterPath shape() const {
189 188 QPainterPath path = QGraphicsLineItem::shape();
190 189 QRectF rect = path.boundingRect();
191 190 path.addRect(rect.adjusted(0, 0, m_axis->orientation() != Qt::Horizontal ? 8 : 0, m_axis->orientation() != Qt::Vertical ? 8 : 0));
192 191 return path;
193 192 }
194 193
195 194 private:
196 195 ChartAxis *m_axis;
197 196 };
198 197
199 198 QTCOMMERCIALCHART_END_NAMESPACE
200 199
201 200 #endif /* CHARTAXI_H */
@@ -1,385 +1,399
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 "charttheme_p.h"
22 22 #include "qchart.h"
23 23 #include "qchart_p.h"
24 24 #include "qchartview.h"
25 25 #include "qlegend.h"
26 26 #include "qabstractaxis.h"
27 27 #include <QTime>
28 28
29 29 //series
30 30 #include "qbarset.h"
31 31 #include "qabstractbarseries.h"
32 32 #include "qstackedbarseries.h"
33 33 #include "qpercentbarseries.h"
34 34 #include "qlineseries.h"
35 35 #include "qareaseries.h"
36 36 #include "qscatterseries.h"
37 37 #include "qpieseries.h"
38 38 #include "qpieslice.h"
39 39 #include "qpieslice_p.h"
40 40 #include "qsplineseries.h"
41 41
42 42 //items
43 43 #include "chartaxis_p.h"
44 44 #include "abstractbarchartitem_p.h"
45 45 #include "stackedbarchartitem_p.h"
46 46 #include "percentbarchartitem_p.h"
47 47 #include "linechartitem_p.h"
48 48 #include "areachartitem_p.h"
49 49 #include "scatterchartitem_p.h"
50 50 #include "piechartitem_p.h"
51 51 #include "splinechartitem_p.h"
52 52
53 53 //themes
54 54 #include "chartthemesystem_p.h"
55 55 #include "chartthemelight_p.h"
56 56 #include "chartthemebluecerulean_p.h"
57 57 #include "chartthemedark_p.h"
58 58 #include "chartthemebrownsand_p.h"
59 59 #include "chartthemebluencs_p.h"
60 60 #include "chartthemehighcontrast_p.h"
61 61 #include "chartthemeblueicy_p.h"
62 62
63 63 QTCOMMERCIALCHART_BEGIN_NAMESPACE
64 64
65 65 ChartTheme::ChartTheme(QChart::ChartTheme id) :
66 66 m_id(id),
67 67 m_masterFont(QFont("arial", 14)),
68 68 m_labelFont(QFont("arial", 10)),
69 69 m_labelBrush(QColor(QRgb(0x000000))),
70 70 m_axisLinePen(QPen(QRgb(0x000000))),
71 71 m_backgroundShadesPen(Qt::NoPen),
72 72 m_backgroundShadesBrush(Qt::NoBrush),
73 73 m_backgroundShades(BackgroundShadesNone),
74 74 m_backgroundDropShadowEnabled(false),
75 75 m_gridLinePen(QPen(QRgb(0x000000))),
76 76 m_force(false)
77 77 {
78 78 qsrand(QTime(0, 0, 0).secsTo(QTime::currentTime()));
79 79 }
80 80
81 81
82 82 ChartTheme *ChartTheme::createTheme(QChart::ChartTheme theme)
83 83 {
84 84 switch (theme) {
85 85 case QChart::ChartThemeLight:
86 86 return new ChartThemeLight();
87 87 case QChart::ChartThemeBlueCerulean:
88 88 return new ChartThemeBlueCerulean();
89 89 case QChart::ChartThemeDark:
90 90 return new ChartThemeDark();
91 91 case QChart::ChartThemeBrownSand:
92 92 return new ChartThemeBrownSand();
93 93 case QChart::ChartThemeBlueNcs:
94 94 return new ChartThemeBlueNcs();
95 95 case QChart::ChartThemeHighContrast:
96 96 return new ChartThemeHighContrast();
97 97 case QChart::ChartThemeBlueIcy:
98 98 return new ChartThemeBlueIcy();
99 99 default:
100 100 return new ChartThemeSystem();
101 101 }
102 102 }
103 103
104 104 void ChartTheme::decorate(QChart *chart)
105 105 {
106 106 QBrush brush;
107 107
108 108 if (m_force || brush == chart->backgroundBrush())
109 109 chart->setBackgroundBrush(m_chartBackgroundGradient);
110 110 chart->setTitleFont(m_masterFont);
111 111 chart->setTitleBrush(m_labelBrush);
112 112 chart->setDropShadowEnabled(m_backgroundDropShadowEnabled);
113 113 }
114 114
115 115 void ChartTheme::decorate(QLegend *legend)
116 116 {
117 117 QPen pen;
118 118 QBrush brush;
119 119 QFont font;
120 120
121 121 if (m_force || pen == legend->pen())
122 122 legend->setPen(m_axisLinePen);
123 123
124 124 if (m_force || brush == legend->brush())
125 125 legend->setBrush(m_chartBackgroundGradient);
126 126
127 127 if (m_force || font == legend->font())
128 128 legend->setFont(m_labelFont);
129 129
130 130 if (m_force || brush == legend->labelBrush())
131 131 legend->setLabelBrush(m_labelBrush);
132 132 }
133 133
134 134 void ChartTheme::decorate(QAreaSeries *series, int index)
135 135 {
136 136 QPen pen;
137 137 QBrush brush;
138 138
139 139 if (m_force || pen == series->pen()) {
140 140 pen.setColor(colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 0.0));
141 141 pen.setWidthF(2);
142 142 series->setPen(pen);
143 143 }
144 144
145 145 if (m_force || brush == series->brush()) {
146 146 QBrush brush(m_seriesColors.at(index % m_seriesColors.size()));
147 147 series->setBrush(brush);
148 148 }
149 149 }
150 150
151 151
152 152 void ChartTheme::decorate(QLineSeries *series, int index)
153 153 {
154 154 QPen pen;
155 155 if (m_force || pen == series->pen()) {
156 156 pen.setColor(m_seriesColors.at(index % m_seriesColors.size()));
157 157 pen.setWidthF(2);
158 158 series->setPen(pen);
159 159 }
160 160 }
161 161
162 162 void ChartTheme::decorate(QAbstractBarSeries *series, int index)
163 163 {
164 164 QBrush brush;
165 165 QPen pen;
166 166 QList<QBarSet *> sets = series->barSets();
167 167
168 168 qreal takeAtPos = 0.5;
169 169 qreal step = 0.2;
170 170 if (sets.count() > 1) {
171 171 step = 1.0 / (qreal) sets.count();
172 172 if (sets.count() % m_seriesGradients.count())
173 173 step *= m_seriesGradients.count();
174 174 else
175 175 step *= (m_seriesGradients.count() - 1);
176 176 }
177 177
178 178 for (int i(0); i < sets.count(); i++) {
179 179 int colorIndex = (index + i) % m_seriesGradients.count();
180 180 if (i > 0 && i % m_seriesGradients.count() == 0) {
181 181 // There is no dedicated base color for each sets, generate more colors
182 182 takeAtPos += step;
183 183 if (takeAtPos == 1.0)
184 184 takeAtPos += step;
185 185 takeAtPos -= (int) takeAtPos;
186 186 }
187 187 if (m_force || brush == sets.at(i)->brush())
188 188 sets.at(i)->setBrush(colorAt(m_seriesGradients.at(colorIndex), takeAtPos));
189 189
190 190 // Pick label color from the opposite end of the gradient.
191 191 // 0.3 as a boundary seems to work well.
192 192 if (m_force || brush == sets.at(i)->labelBrush()) {
193 193 if (takeAtPos < 0.3)
194 194 sets.at(i)->setLabelBrush(colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 1));
195 195 else
196 196 sets.at(i)->setLabelBrush(colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 0));
197 197 }
198 198
199 199 if (m_force || pen == sets.at(i)->pen()) {
200 200 QColor c = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 0.0);
201 201 sets.at(i)->setPen(c);
202 202 }
203 203 }
204 204 }
205 205
206 206 void ChartTheme::decorate(QScatterSeries *series, int index)
207 207 {
208 208 QPen pen;
209 209 QBrush brush;
210 210
211 211 if (m_force || pen == series->pen()) {
212 212 pen.setColor(colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 0.0));
213 213 pen.setWidthF(2);
214 214 series->setPen(pen);
215 215 }
216 216
217 217 if (m_force || brush == series->brush()) {
218 218 QBrush brush(m_seriesColors.at(index % m_seriesColors.size()));
219 219 series->setBrush(brush);
220 220 }
221 221 }
222 222
223 223 void ChartTheme::decorate(QPieSeries *series, int index)
224 224 {
225 225
226 226 for (int i(0); i < series->slices().count(); i++) {
227 227
228 228 QColor penColor = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 0.0);
229 229
230 230 // Get color for a slice from a gradient linearly, beginning from the start of the gradient
231 231 qreal pos = (qreal)(i + 1) / (qreal) series->count();
232 232 QColor brushColor = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), pos);
233 233
234 234 QPieSlice *s = series->slices().at(i);
235 235 QPieSlicePrivate *d = QPieSlicePrivate::fromSlice(s);
236 236
237 237 if (m_force || d->m_data.m_slicePen.isThemed())
238 238 d->setPen(penColor, true);
239 239
240 240 if (m_force || d->m_data.m_sliceBrush.isThemed())
241 241 d->setBrush(brushColor, true);
242 242
243 243 if (m_force || d->m_data.m_labelBrush.isThemed())
244 244 d->setLabelBrush(m_labelBrush.color(), true);
245 245
246 246 if (m_force || d->m_data.m_labelFont.isThemed())
247 247 d->setLabelFont(m_labelFont, true);
248 248 }
249 249 }
250 250
251 251 void ChartTheme::decorate(QSplineSeries *series, int index)
252 252 {
253 253 QPen pen;
254 254 if (m_force || pen == series->pen()) {
255 255 pen.setColor(m_seriesColors.at(index % m_seriesColors.size()));
256 256 pen.setWidthF(2);
257 257 series->setPen(pen);
258 258 }
259 259 }
260 260
261 261 void ChartTheme::decorate(QAbstractAxis *axis)
262 262 {
263 263 QPen pen;
264 264 QBrush brush;
265 265 QFont font;
266 266
267 267 bool axisX = axis->orientation() == Qt::Horizontal;
268 268
269 269 if (axis->isLineVisible()) {
270 270
271 271 if (m_force || brush == axis->labelsBrush())
272 272 axis->setLabelsBrush(m_labelBrush);
273 273
274 //TODO: introduce axis brush
275 if (m_force || brush == axis->titleBrush())
276 axis->setTitleBrush(m_labelBrush);
277
274 278 if (m_force || pen == axis->labelsPen())
275 279 axis->setLabelsPen(Qt::NoPen); // NoPen for performance reasons
276 280
281 if (m_force || pen == axis->titlePen())
282 axis->setTitlePen(Qt::NoPen); // Noen for performance reasons
283
277 284 if (m_force || axis->shadesVisible()) {
278 285
279 286 if (m_force || brush == axis->shadesBrush())
280 287 axis->setShadesBrush(m_backgroundShadesBrush);
281 288
282 289 if (m_force || pen == axis->shadesPen())
283 290 axis->setShadesPen(m_backgroundShadesPen);
284 291
285 292 if (m_force && (m_backgroundShades == BackgroundShadesBoth
286 293 || (m_backgroundShades == BackgroundShadesVertical && axisX)
287 294 || (m_backgroundShades == BackgroundShadesHorizontal && !axisX))) {
288 295 axis->setShadesVisible(true);
289 296 }
290 297 }
291 298
292 299 if (m_force || pen == axis->linePen())
293 300 axis->setLinePen(m_axisLinePen);
294 301
295 302 if (m_force || pen == axis->gridLinePen())
296 303 axis->setGridLinePen(m_gridLinePen);
297 304
298 305 if (m_force || font == axis->labelsFont())
299 306 axis->setLabelsFont(m_labelFont);
307
308 //TODO: discuss with Tero
309 if (m_force || font == axis->titleFont()){
310 QFont font(m_labelFont);
311 font.setBold(true);
312 axis->setTitleFont(font);
313 }
300 314 }
301 315 }
302 316
303 317 void ChartTheme::generateSeriesGradients()
304 318 {
305 319 // Generate gradients in HSV color space
306 320 foreach (const QColor &color, m_seriesColors) {
307 321 QLinearGradient g;
308 322 qreal h = color.hsvHueF();
309 323 qreal s = color.hsvSaturationF();
310 324
311 325 // TODO: tune the algorithm to give nice results with most base colors defined in
312 326 // most themes. The rest of the gradients we can define manually in theme specific
313 327 // implementation.
314 328 QColor start = color;
315 329 start.setHsvF(h, 0.0, 1.0);
316 330 g.setColorAt(0.0, start);
317 331
318 332 g.setColorAt(0.5, color);
319 333
320 334 QColor end = color;
321 335 end.setHsvF(h, s, 0.25);
322 336 g.setColorAt(1.0, end);
323 337
324 338 m_seriesGradients << g;
325 339 }
326 340 }
327 341
328 342
329 343 QColor ChartTheme::colorAt(const QColor &start, const QColor &end, qreal pos)
330 344 {
331 345 Q_ASSERT(pos >= 0.0 && pos <= 1.0);
332 346 qreal r = start.redF() + ((end.redF() - start.redF()) * pos);
333 347 qreal g = start.greenF() + ((end.greenF() - start.greenF()) * pos);
334 348 qreal b = start.blueF() + ((end.blueF() - start.blueF()) * pos);
335 349 QColor c;
336 350 c.setRgbF(r, g, b);
337 351 return c;
338 352 }
339 353
340 354 QColor ChartTheme::colorAt(const QGradient &gradient, qreal pos)
341 355 {
342 356 Q_ASSERT(pos >= 0 && pos <= 1.0);
343 357
344 358 QGradientStops stops = gradient.stops();
345 359 int count = stops.count();
346 360
347 361 // find previous stop relative to position
348 362 QGradientStop prev = stops.first();
349 363 for (int i = 0; i < count; i++) {
350 364 QGradientStop stop = stops.at(i);
351 365 if (pos > stop.first)
352 366 prev = stop;
353 367
354 368 // given position is actually a stop position?
355 369 if (pos == stop.first) {
356 370 //qDebug() << "stop color" << pos;
357 371 return stop.second;
358 372 }
359 373 }
360 374
361 375 // find next stop relative to position
362 376 QGradientStop next = stops.last();
363 377 for (int i = count - 1; i >= 0; i--) {
364 378 QGradientStop stop = stops.at(i);
365 379 if (pos < stop.first)
366 380 next = stop;
367 381 }
368 382
369 383 //qDebug() << "prev" << prev.first << "pos" << pos << "next" << next.first;
370 384
371 385 qreal range = next.first - prev.first;
372 386 qreal posDelta = pos - prev.first;
373 387 qreal relativePos = posDelta / range;
374 388
375 389 //qDebug() << "range" << range << "posDelta" << posDelta << "relativePos" << relativePos;
376 390
377 391 return colorAt(prev.second, next.second, relativePos);
378 392 }
379 393
380 394 void ChartTheme::setForced(bool enabled)
381 395 {
382 396 m_force = enabled;
383 397 }
384 398
385 399 QTCOMMERCIALCHART_END_NAMESPACE
General Comments 0
You need to be logged in to leave comments. Login now