##// END OF EJS Templates
legend theme fix
sauimone -
r1527:14e346f15b06
parent child
Show More
@@ -1,383 +1,391
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 "qaxis.h"
27 27 #include <QTime>
28 28
29 29 //series
30 30 #include "qbarset.h"
31 31 #include "qbarseries.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 "barchartitem_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_masterFont(QFont("arial", 14)),
67 67 m_labelFont(QFont("arial", 10)),
68 68 m_titleBrush(QColor(QRgb(0x000000))),
69 69 m_axisLinePen(QPen(QRgb(0x000000))),
70 70 m_axisLabelBrush(QColor(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 m_id = id;
79 79 qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
80 80 }
81 81
82 82
83 83 ChartTheme* ChartTheme::createTheme(QChart::ChartTheme theme)
84 84 {
85 85 switch(theme) {
86 86 case QChart::ChartThemeLight:
87 87 return new ChartThemeLight();
88 88 case QChart::ChartThemeBlueCerulean:
89 89 return new ChartThemeBlueCerulean();
90 90 case QChart::ChartThemeDark:
91 91 return new ChartThemeDark();
92 92 case QChart::ChartThemeBrownSand:
93 93 return new ChartThemeBrownSand();
94 94 case QChart::ChartThemeBlueNcs:
95 95 return new ChartThemeBlueNcs();
96 96 case QChart::ChartThemeHighContrast:
97 97 return new ChartThemeHighContrast();
98 98 case QChart::ChartThemeBlueIcy:
99 99 return new ChartThemeBlueIcy();
100 100 default:
101 101 return new ChartThemeSystem();
102 102 }
103 103 }
104 104
105 105 void ChartTheme::decorate(QChart *chart)
106 106 {
107 107 QBrush brush;
108 108
109 109 if(brush == chart->backgroundBrush() || m_force)
110 110 chart->setBackgroundBrush(m_chartBackgroundGradient);
111 111 chart->setTitleFont(m_masterFont);
112 112 chart->setTitleBrush(m_titleBrush);
113 113 chart->setDropShadowEnabled(m_backgroundDropShadowEnabled);
114 114 }
115 115
116 116 void ChartTheme::decorate(QLegend *legend)
117 117 {
118 118 QPen pen;
119 119 QBrush brush;
120 QFont font;
120 121
121 122 if (pen == legend->pen() || m_force)
122 123 legend->setPen(m_axisLinePen);
123 124
124 125 if (brush == legend->brush() || m_force)
125 126 legend->setBrush(m_chartBackgroundGradient);
127
128 // TODO: should legend have own brush & font defined by theme?
129 if (font == legend->font() || m_force)
130 legend->setFont(m_labelFont);
131
132 if (brush == legend->labelBrush() || m_force)
133 legend->setLabelBrush(m_axisLabelBrush);
126 134 }
127 135
128 136 void ChartTheme::decorate(QAreaSeries *series, int index)
129 137 {
130 138 QPen pen;
131 139 QBrush brush;
132 140
133 141 if (pen == series->pen() || m_force){
134 142 pen.setColor(colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 0.0));
135 143 pen.setWidthF(2);
136 144 series->setPen(pen);
137 145 }
138 146
139 147 if (brush == series->brush() || m_force) {
140 148 QBrush brush(m_seriesColors.at(index % m_seriesColors.size()));
141 149 series->setBrush(brush);
142 150 }
143 151 }
144 152
145 153
146 154 void ChartTheme::decorate(QLineSeries *series,int index)
147 155 {
148 156 QPen pen;
149 157 if(pen == series->pen() || m_force ){
150 158 pen.setColor(m_seriesColors.at(index%m_seriesColors.size()));
151 159 pen.setWidthF(2);
152 160 series->setPen(pen);
153 161 }
154 162 }
155 163
156 164 void ChartTheme::decorate(QBarSeries *series, int index)
157 165 {
158 166 QBrush brush;
159 167 QPen pen;
160 168 QList<QBarSet *> sets = series->barSets();
161 169
162 170 qreal takeAtPos = 0.5;
163 171 qreal step = 0.2;
164 172 if (sets.count() > 1 ) {
165 173 step = 1.0 / (qreal) sets.count();
166 174 if (sets.count() % m_seriesGradients.count())
167 175 step *= m_seriesGradients.count();
168 176 else
169 177 step *= (m_seriesGradients.count() - 1);
170 178 }
171 179
172 180 for (int i(0); i < sets.count(); i++) {
173 181 int colorIndex = (index + i) % m_seriesGradients.count();
174 182 if (i > 0 && i % m_seriesGradients.count() == 0) {
175 183 // There is no dedicated base color for each sets, generate more colors
176 184 takeAtPos += step;
177 185 if (takeAtPos == 1.0)
178 186 takeAtPos += step;
179 187 takeAtPos -= (int) takeAtPos;
180 188 }
181 189 if (brush == sets.at(i)->brush() || m_force )
182 190 sets.at(i)->setBrush(colorAt(m_seriesGradients.at(colorIndex), takeAtPos));
183 191
184 192 // Pick label color from the opposite end of the gradient.
185 193 // 0.3 as a boundary seems to work well.
186 194 if (takeAtPos < 0.3)
187 195 sets.at(i)->setLabelBrush(colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 1));
188 196 else
189 197 sets.at(i)->setLabelBrush(colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 0));
190 198
191 199 if (pen == sets.at(i)->pen() || m_force) {
192 200 QColor c = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 0.0);
193 201 sets.at(i)->setPen(c);
194 202 }
195 203 }
196 204 }
197 205
198 206 void ChartTheme::decorate(QScatterSeries *series, int index)
199 207 {
200 208 QPen pen;
201 209 QBrush brush;
202 210
203 211 if (pen == series->pen() || m_force) {
204 212 pen.setColor(colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 0.0));
205 213 pen.setWidthF(2);
206 214 series->setPen(pen);
207 215 }
208 216
209 217 if (brush == series->brush() || m_force) {
210 218 QBrush brush(m_seriesColors.at(index % m_seriesColors.size()));
211 219 series->setBrush(brush);
212 220 }
213 221 }
214 222
215 223 void ChartTheme::decorate(QPieSeries *series, int index)
216 224 {
217 225
218 226 for (int i(0); i < series->slices().count(); i++) {
219 227
220 228 QColor penColor = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 0.0);
221 229
222 230 // Get color for a slice from a gradient linearly, beginning from the start of the gradient
223 231 qreal pos = (qreal) (i + 1) / (qreal) series->count();
224 232 QColor brushColor = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), pos);
225 233
226 234 QPieSlice *s = series->slices().at(i);
227 235 QPieSlicePrivate *d = QPieSlicePrivate::fromSlice(s);
228 236
229 237 if (d->m_data.m_slicePen.isThemed() || m_force)
230 238 d->setPen(penColor, true);
231 239
232 240 if (d->m_data.m_sliceBrush.isThemed() || m_force)
233 241 d->setBrush(brushColor, true);
234 242
235 243 if (d->m_data.m_labelBrush.isThemed() || m_force)
236 244 d->setLabelBrush(QBrush(m_titleBrush.color()), true);
237 245
238 246 if (d->m_data.m_labelFont.isThemed() || m_force)
239 247 d->setLabelFont(m_labelFont, true);
240 248 }
241 249 }
242 250
243 251 void ChartTheme::decorate(QSplineSeries *series, int index)
244 252 {
245 253 QPen pen;
246 254 if(pen == series->pen() || m_force){
247 255 pen.setColor(m_seriesColors.at(index%m_seriesColors.size()));
248 256 pen.setWidthF(2);
249 257 series->setPen(pen);
250 258 }
251 259 }
252 260
253 261 void ChartTheme::decorate(QAxis *axis,bool axisX)
254 262 {
255 263 QPen pen;
256 264 QBrush brush;
257 265 QFont font;
258 266
259 267 if (axis->isAxisVisible()) {
260 268
261 269 if(brush == axis->labelsBrush() || m_force){
262 270 axis->setLabelsBrush(m_axisLabelBrush);
263 271 }
264 272 if(pen == axis->labelsPen() || m_force){
265 273 axis->setLabelsPen(Qt::NoPen); // NoPen for performance reasons
266 274 }
267 275
268 276
269 277 if (axis->shadesVisible() || m_force) {
270 278
271 279 if(brush == axis->shadesBrush() || m_force){
272 280 axis->setShadesBrush(m_backgroundShadesBrush);
273 281 }
274 282
275 283 if(pen == axis->shadesPen() || m_force){
276 284 axis->setShadesPen(m_backgroundShadesPen);
277 285 }
278 286
279 287 if( m_force && (m_backgroundShades == BackgroundShadesBoth
280 288 || (m_backgroundShades == BackgroundShadesVertical && axisX)
281 289 || (m_backgroundShades == BackgroundShadesHorizontal && !axisX))){
282 290 axis->setShadesVisible(true);
283 291
284 292 }
285 293 }
286 294
287 295 if(pen == axis->axisPen() || m_force){
288 296 axis->setAxisPen(m_axisLinePen);
289 297 }
290 298
291 299 if(pen == axis->gridLinePen() || m_force){
292 300 axis->setGridLinePen(m_gridLinePen);
293 301 }
294 302
295 303 if(font == axis->labelsFont() || m_force){
296 304 axis->setLabelsFont(m_labelFont);
297 305 }
298 306 }
299 307 }
300 308
301 309 void ChartTheme::generateSeriesGradients()
302 310 {
303 311 // Generate gradients in HSV color space
304 312 foreach (const QColor& color, m_seriesColors) {
305 313 QLinearGradient g;
306 314 qreal h = color.hsvHueF();
307 315 qreal s = color.hsvSaturationF();
308 316
309 317 // TODO: tune the algorithm to give nice results with most base colors defined in
310 318 // most themes. The rest of the gradients we can define manually in theme specific
311 319 // implementation.
312 320 QColor start = color;
313 321 start.setHsvF(h, 0.0, 1.0);
314 322 g.setColorAt(0.0, start);
315 323
316 324 g.setColorAt(0.5, color);
317 325
318 326 QColor end = color;
319 327 end.setHsvF(h, s, 0.25);
320 328 g.setColorAt(1.0, end);
321 329
322 330 m_seriesGradients << g;
323 331 }
324 332 }
325 333
326 334
327 335 QColor ChartTheme::colorAt(const QColor &start, const QColor &end, qreal pos)
328 336 {
329 337 Q_ASSERT(pos >= 0.0 && pos <= 1.0);
330 338 qreal r = start.redF() + ((end.redF() - start.redF()) * pos);
331 339 qreal g = start.greenF() + ((end.greenF() - start.greenF()) * pos);
332 340 qreal b = start.blueF() + ((end.blueF() - start.blueF()) * pos);
333 341 QColor c;
334 342 c.setRgbF(r, g, b);
335 343 return c;
336 344 }
337 345
338 346 QColor ChartTheme::colorAt(const QGradient &gradient, qreal pos)
339 347 {
340 348 Q_ASSERT(pos >= 0 && pos <= 1.0);
341 349
342 350 QGradientStops stops = gradient.stops();
343 351 int count = stops.count();
344 352
345 353 // find previous stop relative to position
346 354 QGradientStop prev = stops.first();
347 355 for (int i = 0; i < count; i++) {
348 356 QGradientStop stop = stops.at(i);
349 357 if (pos > stop.first)
350 358 prev = stop;
351 359
352 360 // given position is actually a stop position?
353 361 if (pos == stop.first) {
354 362 //qDebug() << "stop color" << pos;
355 363 return stop.second;
356 364 }
357 365 }
358 366
359 367 // find next stop relative to position
360 368 QGradientStop next = stops.last();
361 369 for (int i = count - 1; i >= 0; i--) {
362 370 QGradientStop stop = stops.at(i);
363 371 if (pos < stop.first)
364 372 next = stop;
365 373 }
366 374
367 375 //qDebug() << "prev" << prev.first << "pos" << pos << "next" << next.first;
368 376
369 377 qreal range = next.first - prev.first;
370 378 qreal posDelta = pos - prev.first;
371 379 qreal relativePos = posDelta / range;
372 380
373 381 //qDebug() << "range" << range << "posDelta" << posDelta << "relativePos" << relativePos;
374 382
375 383 return colorAt(prev.second, next.second, relativePos);
376 384 }
377 385
378 386 void ChartTheme::setForced(bool enabled)
379 387 {
380 388 m_force=enabled;
381 389 }
382 390
383 391 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,209 +1,231
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 "legendmarker_p.h"
22 22 #include "qxyseries.h"
23 23 #include "qxyseries_p.h"
24 24 #include "qlegend.h"
25 25 #include "qbarseries.h"
26 26 #include "qpieseries.h"
27 27 #include "qpieslice.h"
28 28 #include "qbarset.h"
29 29 #include "qbarset_p.h"
30 30 #include "qareaseries.h"
31 31 #include "qareaseries_p.h"
32 32 #include <QPainter>
33 33 #include <QGraphicsSceneEvent>
34 34 #include <QGraphicsSimpleTextItem>
35 35 #include <QDebug>
36 36
37 37 QTCOMMERCIALCHART_BEGIN_NAMESPACE
38 38
39 39 LegendMarker::LegendMarker(QAbstractSeries *series, QLegend *legend) :
40 40 QGraphicsObject(legend),
41 41 m_series(series),
42 42 m_markerRect(0,0,10.0,10.0),
43 43 m_boundingRect(0,0,0,0),
44 44 m_legend(legend),
45 45 m_textItem(new QGraphicsSimpleTextItem(this)),
46 46 m_rectItem(new QGraphicsRectItem(this))
47 47 {
48 48 //setAcceptedMouseButtons(Qt::LeftButton|Qt::RightButton);
49 49 m_rectItem->setRect(m_markerRect);
50 50 updateLayout();
51 51 }
52 52
53 53 void LegendMarker::setPen(const QPen &pen)
54 54 {
55 55 m_textItem->setPen(pen);
56 56 updateLayout();
57 57 }
58 58
59 59 QPen LegendMarker::pen() const
60 60 {
61 61 return m_textItem->pen();
62 62 }
63 63
64 64 void LegendMarker::setBrush(const QBrush &brush)
65 65 {
66 66 m_rectItem->setBrush(brush);
67 67 }
68 68
69 69 QBrush LegendMarker::brush() const
70 70 {
71 71 return m_rectItem->brush();
72 72 }
73 73
74 74 void LegendMarker::setFont(const QFont &font)
75 75 {
76 76 m_textItem->setFont(font);
77 77 updateLayout();
78 78 }
79 79
80 80 QFont LegendMarker::font() const
81 81 {
82 82 return m_textItem->font();
83 83 }
84 84
85 85 void LegendMarker::setLabel(const QString label)
86 86 {
87 87 m_textItem->setText(label);
88 88 updateLayout();
89 89 }
90 90
91 91 void LegendMarker::setSize(const QSize& size)
92 92 {
93 93 m_markerRect = QRectF(0,0,size.width(),size.height());
94 94 }
95 95
96 96 QString LegendMarker::label() const
97 97 {
98 98 return m_textItem->text();
99 99 }
100 100
101 void LegendMarker::setLabelBrush(const QBrush &brush)
102 {
103 m_textItem->setBrush(brush);
104 updateLayout();
105 }
106
107 QBrush LegendMarker::labelBrush() const
108 {
109 return m_textItem->brush();
110 }
111
112 void LegendMarker::setLabelPen(const QPen &pen)
113 {
114 m_textItem->setPen(pen);
115 updateLayout();
116 }
117
118 QPen LegendMarker::labelPen() const
119 {
120 return m_textItem->pen();
121 }
122
101 123 void LegendMarker::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
102 124 {
103 125 Q_UNUSED(option)
104 126 Q_UNUSED(widget)
105 127 Q_UNUSED(painter)
106 128 }
107 129
108 130 QRectF LegendMarker::boundingRect() const
109 131 {
110 132 return m_boundingRect;
111 133 }
112 134
113 135 void LegendMarker::updateLayout()
114 136 {
115 137
116 138 static const qreal margin = 2;
117 139 static const qreal space = 4;
118 140
119 141 const QRectF& textRect = m_textItem->boundingRect();
120 142 prepareGeometryChange();
121 143 m_boundingRect = QRectF(0,0,m_markerRect.width() + 2*margin + space + textRect.width(),qMax(m_markerRect.height()+2*margin,textRect.height()+2*margin));
122 144 m_textItem->setPos(m_markerRect.width() + space + margin,m_boundingRect.height()/2 - textRect.height()/2);
123 145 m_rectItem->setPos(margin,m_boundingRect.height()/2 - m_markerRect.height()/2);
124 146
125 147 }
126 148
127 149 void LegendMarker::mousePressEvent(QGraphicsSceneMouseEvent *event)
128 150 {
129 151 QGraphicsObject::mousePressEvent(event);
130 152 qDebug()<<"Not implemented"; //TODO: selected signal removed for now
131 153 }
132 154
133 155 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
134 156
135 157 AreaLegendMarker::AreaLegendMarker(QAreaSeries *series,QLegend *legend) : LegendMarker(series,legend),
136 158 m_series(series)
137 159 {
138 160 //QObject::connect(this, SIGNAL(selected()), series, SIGNAL(selected()));
139 161 QObject::connect(series->d_func(),SIGNAL(updated()), this, SLOT(updated()));
140 162 QObject::connect(series, SIGNAL(nameChanged()), this, SLOT(updated()));
141 163 updated();
142 164 }
143 165
144 166 void AreaLegendMarker::updated()
145 167 {
146 168 setBrush(m_series->brush());
147 169 setLabel(m_series->name());
148 170 }
149 171
150 172 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
151 173
152 174 BarLegendMarker::BarLegendMarker(QBarSeries *barseries,QBarSet *barset, QLegend *legend) : LegendMarker(barseries,legend),
153 175 m_barset(barset)
154 176 {
155 177 //QObject::connect(this, SIGNAL(selected()),barset->d_ptr.data(), SIGNAL(selected()));
156 178 QObject::connect(barset->d_ptr.data(), SIGNAL(updatedBars()), this, SLOT(updated()));
157 179 updated();
158 180 }
159 181
160 182 void BarLegendMarker::updated()
161 183 {
162 184 setBrush(m_barset->brush());
163 185 setLabel(m_barset->label());
164 186 }
165 187
166 188 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
167 189
168 190 PieLegendMarker::PieLegendMarker(QPieSeries* series,QPieSlice *pieslice, QLegend *legend) : LegendMarker(series,legend),
169 191 m_pieslice(pieslice)
170 192 {
171 193 QObject::connect(pieslice, SIGNAL(labelChanged()), this, SLOT(updated()));
172 194 QObject::connect(pieslice, SIGNAL(brushChanged()), this, SLOT(updated()));
173 195 updated();
174 196 }
175 197
176 198 void PieLegendMarker::updated()
177 199 {
178 200 setBrush(m_pieslice->brush());
179 201 setLabel(m_pieslice->label());
180 202 }
181 203
182 204 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
183 205
184 206 XYLegendMarker::XYLegendMarker(QXYSeries *series, QLegend *legend) : LegendMarker(series,legend),
185 207 m_series(series)
186 208 {
187 209 //QObject::connect(this, SIGNAL(selected()), series, SIGNAL(selected()));
188 210 QObject::connect(series->d_func(),SIGNAL(updated()), this, SLOT(updated()));
189 211 QObject::connect(series, SIGNAL(nameChanged()), this, SLOT(updated()));
190 212 updated();
191 213 }
192 214
193 215 void XYLegendMarker::updated()
194 216 {
195 217 setLabel(m_series->name());
196 218
197 219 if(m_series->type()== QAbstractSeries::SeriesTypeScatter)
198 220 {
199 221 setBrush(m_series->brush());
200 222
201 223 }
202 224 else {
203 225 setBrush(QBrush(m_series->pen().color()));
204 226 }
205 227 }
206 228
207 229 #include "moc_legendmarker_p.cpp"
208 230
209 231 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,137 +1,141
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 LEGENDMARKER_P_H
31 31 #define LEGENDMARKER_P_H
32 32
33 33 #include "qchartglobal.h"
34 34 #include <QGraphicsObject>
35 35 #include <QBrush>
36 36 #include <QPen>
37 37 #include <QGraphicsSimpleTextItem>
38 38
39 39 QTCOMMERCIALCHART_BEGIN_NAMESPACE
40 40
41 41 class QAbstractSeries;
42 42 class QAreaSeries;
43 43 class QXYSeries;
44 44 class QBarSet;
45 45 class QBarSeries;
46 46 class QPieSlice;
47 47 class QLegend;
48 48 class QPieSeries;
49 49
50 50 class LegendMarker : public QGraphicsObject
51 51 {
52 52 Q_OBJECT
53 53
54 54 public:
55 55 explicit LegendMarker(QAbstractSeries *m_series, QLegend *parent);
56 56
57 57 void setPen(const QPen &pen);
58 58 QPen pen() const;
59 59 void setBrush(const QBrush &brush);
60 60 QBrush brush() const;
61 61
62 62 void setFont(const QFont &font);
63 63 QFont font() const;
64 64
65 65 void setSize(const QSize& size);
66 66
67 67 void setLabel(const QString label);
68 68 QString label() const;
69 void setLabelBrush(const QBrush &brush);
70 QBrush labelBrush() const;
71 void setLabelPen(const QPen &pen);
72 QPen labelPen() const;
69 73
70 74 QAbstractSeries *series() const { return m_series;}
71 75
72 76 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
73 77
74 78 QRectF boundingRect() const;
75 79
76 80 void updateLayout();
77 81
78 82 protected:
79 83 // From QGraphicsObject
80 84 void mousePressEvent(QGraphicsSceneMouseEvent *event);
81 85
82 86 public Q_SLOTS:
83 87 virtual void updated() = 0;
84 88
85 89 protected:
86 90 QAbstractSeries *m_series;
87 91 QRectF m_markerRect;
88 92 QRectF m_boundingRect;
89 93 QLegend* m_legend;
90 94 QGraphicsSimpleTextItem *m_textItem;
91 95 QGraphicsRectItem *m_rectItem;
92 96
93 97 };
94 98
95 99 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
96 100 class XYLegendMarker : public LegendMarker
97 101 {
98 102 public:
99 103 XYLegendMarker(QXYSeries *series, QLegend *legend);
100 104 protected:
101 105 void updated();
102 106 private:
103 107 QXYSeries *m_series;
104 108 };
105 109 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
106 110 class AreaLegendMarker : public LegendMarker
107 111 {
108 112 public:
109 113 AreaLegendMarker(QAreaSeries *series, QLegend *legend);
110 114 protected:
111 115 void updated();
112 116 private:
113 117 QAreaSeries *m_series;
114 118 };
115 119 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
116 120 class BarLegendMarker : public LegendMarker
117 121 {
118 122 public:
119 123 BarLegendMarker(QBarSeries *barseries, QBarSet *barset,QLegend *legend);
120 124 protected:
121 125 void updated();
122 126 private:
123 127 QBarSet *m_barset;
124 128 };
125 129 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
126 130 class PieLegendMarker : public LegendMarker
127 131 {
128 132 public:
129 133 PieLegendMarker(QPieSeries *pieSeries, QPieSlice *pieslice, QLegend *legend);
130 134 protected:
131 135 void updated();
132 136 private:
133 137 QPieSlice *m_pieslice;
134 138 };
135 139
136 140 QTCOMMERCIALCHART_END_NAMESPACE
137 141 #endif // LEGENDMARKER_P_H
@@ -1,801 +1,873
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 "qlegend.h"
22 22 #include "qlegend_p.h"
23 23 #include "qabstractseries.h"
24 24 #include "qabstractseries_p.h"
25 25 #include "qchart_p.h"
26 26
27 27 #include "legendmarker_p.h"
28 28 #include "qxyseries.h"
29 29 #include "qlineseries.h"
30 30 #include "qareaseries.h"
31 31 #include "qscatterseries.h"
32 32 #include "qsplineseries.h"
33 33 #include "qbarseries.h"
34 34 #include "qstackedbarseries.h"
35 35 #include "qpercentbarseries.h"
36 36 #include "qbarset.h"
37 37 #include "qpieseries.h"
38 38 #include "qpieseries_p.h"
39 39 #include "qpieslice.h"
40 40 #include "chartpresenter_p.h"
41 41 #include <QPainter>
42 42 #include <QPen>
43 43 #include <QTimer>
44 44
45 45 #include <QGraphicsSceneEvent>
46 46
47 47 QTCOMMERCIALCHART_BEGIN_NAMESPACE
48 48
49 49 /*!
50 50 \class QLegend
51 51 \brief Legend object
52 52 \mainclass
53 53
54 54 QLegend is a graphical object, whics displays legend of the chart. Legend state is updated by QChart, when
55 55 series have been changed. By default, legend is drawn by QChart, but user can set a new parent to legend and
56 56 handle the drawing manually.
57 57 User isn't supposed to create or delete legend objects, but can reference it via QChart class.
58 58
59 59 \image examples_percentbarchart_legend.png
60 60
61 61 \sa QChart
62 62 */
63 63 /*!
64 64 \qmlclass Legend QLegend
65 65 \brief Legend is part of QtCommercial Chart QML API.
66 66
67 67 Legend is a graphical object, whics displays legend of the chart. Legend state is updated by ChartView, when
68 68 series have been changed. Legend is used via ChartView class. For example:
69 69 \code
70 70 ChartView {
71 71 legend.visible: true
72 72 legend.alignment: Qt.AlignBottom
73 73 // Add a few series...
74 74 }
75 75 \endcode
76 76
77 77 \image examples_percentbarchart_legend.png
78 78 */
79 79
80 80 /*!
81 81 \property QLegend::alignment
82 82 \brief The alignment of the legend.
83 83
84 84 Legend paints on the defined position in the chart. The following alignments are supported:
85 85 Qt::AlignTop, Qt::AlignBottom, Qt::AlignLeft, Qt::AlignRight. If you set more than one flag the result is undefined.
86 86 */
87 87 /*!
88 88 \qmlproperty Qt.Alignment Legend::alignment
89 89 \brief The alignment of the legend.
90 90
91 91 Legend paints on the defined position in the chart. The following alignments are supported:
92 92 Qt.AlignTop, Qt.AlignBottom, Qt.AlignLeft, Qt.AlignRight. If you set more than one flag the result is undefined.
93 93 */
94 94
95 95 /*!
96 96 \property QLegend::backgroundVisible
97 97 Whether the legend background is visible or not.
98 98 */
99 99 /*!
100 100 \qmlproperty bool Legend::backgroundVisible
101 101 Whether the legend background is visible or not.
102 102 */
103 103
104 104 /*!
105 105 \property QLegend::color
106 106 The color of the legend, i.e. the background (brush) color. Note that if you change the color
107 107 of the legend, the style of the legend brush is set to Qt::SolidPattern.
108 108 */
109 109 /*!
110 110 \qmlproperty color Legend::color
111 111 The color of the legend, i.e. the background (brush) color.
112 112 */
113 113
114 114 /*!
115 115 \property QLegend::borderColor
116 116 The border color of the legend, i.e. the line color.
117 117 */
118 118 /*!
119 119 \qmlproperty color Legend::borderColor
120 120 The border color of the legend, i.e. the line color.
121 121 */
122 122
123 123 /*!
124 124 \property QLegend::font
125 125 The font of markers used by legend
126 126 */
127 127 /*!
128 128 \qmlproperty color Legend::font
129 129 The font of markers used by legend
130 130 */
131 131
132 132 /*!
133 133 \fn void QLegend::backgroundVisibleChanged(bool)
134 134 The visibility of the legend background changed to \a visible.
135 135 */
136 136
137 137 /*!
138 138 \fn void QLegend::colorChanged(QColor)
139 139 The color of the legend background changed to \a color.
140 140 */
141 141
142 142 /*!
143 143 \fn void QLegend::borderColorChanged(QColor)
144 144 The border color of the legend background changed to \a color.
145 145 */
146 146
147 147 /*!
148 148 \fn void QLegend::fontChanged(QFont)
149 149 The font of markers of the legend changed to \a font.
150 150 */
151 151
152 152 /*!
153 153 \fn qreal QLegend::minWidth() const
154 154 Returns minimum width of the legend
155 155 */
156 156
157 157 /*!
158 158 \fn qreal QLegend::minHeight() const
159 159 Returns minimum height of the legend
160 160 */
161 161
162 162 /*!
163 163 Constructs the legend object and sets the parent to \a parent
164 164 */
165 165
166 166 QLegend::QLegend(QChart *chart):QGraphicsWidget(chart),
167 167 d_ptr(new QLegendPrivate(chart->d_ptr->m_presenter,chart,this))
168 168 {
169 169 setZValue(ChartPresenter::LegendZValue);
170 170 setFlags(QGraphicsItem::ItemClipsChildrenToShape);
171 171 QObject::connect(chart->d_ptr->m_dataset,SIGNAL(seriesAdded(QAbstractSeries*,Domain*)),d_ptr.data(),SLOT(handleSeriesAdded(QAbstractSeries*,Domain*)));
172 172 QObject::connect(chart->d_ptr->m_dataset,SIGNAL(seriesRemoved(QAbstractSeries*)),d_ptr.data(),SLOT(handleSeriesRemoved(QAbstractSeries*)));
173 173 QObject::connect(chart->d_ptr->m_dataset,SIGNAL(seriesUpdated(QAbstractSeries*)),d_ptr.data(),SLOT(handleSeriesUpdated(QAbstractSeries*)));
174 174 }
175 175
176 176 /*!
177 177 Destroys the legend object. Legend is always owned by a QChart, so an application should never call this.
178 178 */
179 179 QLegend::~QLegend()
180 180 {
181 181 }
182 182
183 183 /*!
184 184 \internal
185 185 */
186 186 void QLegend::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
187 187 {
188 188 Q_UNUSED(option)
189 189 Q_UNUSED(widget)
190 190 if(!d_ptr->m_backgroundVisible) return;
191 191
192 192 painter->setOpacity(opacity());
193 193 painter->setPen(d_ptr->m_pen);
194 194 painter->setBrush(d_ptr->m_brush);
195 195 painter->drawRoundRect(rect(),d_ptr->roundness(rect().width()),d_ptr->roundness(rect().height()));
196 196 }
197 197
198 198 /*!
199 199 \internal
200 200 */
201 201 QRectF QLegend::boundingRect() const
202 202 {
203 203 return d_ptr->m_rect;
204 204 }
205 205
206 206 /*!
207 207 Sets the \a brush of legend. Brush affects the background of legend.
208 208 */
209 209 void QLegend::setBrush(const QBrush &brush)
210 210 {
211 211 if (d_ptr->m_brush != brush) {
212 212 d_ptr->m_brush = brush;
213 213 update();
214 214 }
215 215 }
216 216
217 217 /*!
218 218 Returns the brush used by legend.
219 219 */
220 220 QBrush QLegend::brush() const
221 221 {
222 222 return d_ptr->m_brush;
223 223 }
224 224
225 225 void QLegend::setColor(QColor color)
226 226 {
227 227 QBrush b = d_ptr->m_brush;
228 228 if (b.style() != Qt::SolidPattern || b.color() != color) {
229 229 b.setStyle(Qt::SolidPattern);
230 230 b.setColor(color);
231 231 setBrush(b);
232 232 emit colorChanged(color);
233 233 }
234 234 }
235 235
236 236 QColor QLegend::color()
237 237 {
238 238 return d_ptr->m_brush.color();
239 239 }
240 240
241 241 /*!
242 242 Sets the \a pen of legend. Pen affects the legend borders.
243 243 */
244 244 void QLegend::setPen(const QPen &pen)
245 245 {
246 246 if (d_ptr->m_pen != pen) {
247 247 d_ptr->m_pen = pen;
248 248 update();
249 249 }
250 250 }
251 251
252 252 /*!
253 253 Returns the pen used by legend
254 254 */
255 255
256 256 QPen QLegend::pen() const
257 257 {
258 258 return d_ptr->m_pen;
259 259 }
260 260
261 261 void QLegend::setBorderColor(QColor color)
262 262 {
263 263 QPen p = d_ptr->m_pen;
264 264 if (p.color() != color) {
265 265 p.setColor(color);
266 266 setPen(p);
267 267 emit borderColorChanged(color);
268 268 }
269 269 }
270 270
271 271 QColor QLegend::borderColor()
272 272 {
273 273 return d_ptr->m_pen.color();
274 274 }
275 275
276 276 void QLegend::setFont(const QFont &font)
277 277 {
278 278 if (d_ptr->m_font != font) {
279 279 d_ptr->setFont(font);
280 280 emit fontChanged(font);
281 281 }
282 282 }
283 283
284 284 QFont QLegend::font() const
285 285 {
286 286 return d_ptr->m_font;
287 287 }
288 288
289 void QLegend::setLabelPen(const QPen &pen)
290 {
291 if (d_ptr->m_labelPen != pen) {
292 d_ptr->setLabelPen(pen);
293 emit labelPenChanged(pen);
294 }
295 }
296
297 QPen QLegend::labelPen() const
298 {
299 return d_ptr->m_labelPen;
300 }
301
302 void QLegend::setLabelBrush(const QBrush &brush)
303 {
304 qDebug() << "setting legend brush 1";
305 if (d_ptr->m_labelBrush != brush) {
306 d_ptr->setLabelBrush(brush);
307 emit labelBrushChanged(brush);
308 qDebug() << "setting legend brush 2";
309 }
310 }
311
312 QBrush QLegend::labelBrush() const
313 {
314 return d_ptr->m_labelBrush;
315 }
316
317 void QLegend::setLabelColor(QColor color)
318 {
319 QBrush b = d_ptr->m_labelBrush;
320 if (b.style() != Qt::SolidPattern || b.color() != color) {
321 b.setStyle(Qt::SolidPattern);
322 b.setColor(color);
323 setLabelBrush(b);
324 emit labelColorChanged(color);
325 }
326 }
327
328 QColor QLegend::labelColor() const
329 {
330 return d_ptr->m_labelBrush.color();
331 }
332
289 333 void QLegend::setAlignment(Qt::Alignment alignment)
290 334 {
291 335 if(d_ptr->m_alignment!=alignment) {
292 336 d_ptr->m_alignment = alignment;
293 337 d_ptr->updateLayout();
294 338 }
295 339 }
296 340
297 341 Qt::Alignment QLegend::alignment() const
298 342 {
299 343 return d_ptr->m_alignment;
300 344 }
301 345
302 346 /*!
303 347 Detaches the legend from chart. Chart won't change layout of the legend.
304 348 */
305 349 void QLegend::detachFromChart()
306 350 {
307 351 d_ptr->m_attachedToChart = false;
308 352 }
309 353
310 354 /*!
311 355 Attaches the legend to chart. Chart may change layout of the legend.
312 356 */
313 357 void QLegend::attachToChart()
314 358 {
315 359 d_ptr->attachToChart();
316 360 }
317 361
318 362 /*!
319 363 Returns true, if legend is attached to chart.
320 364 */
321 365 bool QLegend::isAttachedToChart()
322 366 {
323 367 return d_ptr->m_attachedToChart;
324 368 }
325 369
326 370 /*!
327 371 Sets the visibility of legend background to \a visible
328 372 */
329 373 void QLegend::setBackgroundVisible(bool visible)
330 374 {
331 375 if(d_ptr->m_backgroundVisible != visible) {
332 376 d_ptr->m_backgroundVisible = visible;
333 377 update();
334 378 emit backgroundVisibleChanged(visible);
335 379 }
336 380 }
337 381
338 382 /*!
339 383 Returns the visibility of legend background
340 384 */
341 385 bool QLegend::isBackgroundVisible() const
342 386 {
343 387 return d_ptr->m_backgroundVisible;
344 388 }
345 389
346 390 /*!
347 391 \internal \a event see QGraphicsWidget for details
348 392 */
349 393 void QLegend::resizeEvent(QGraphicsSceneResizeEvent *event)
350 394 {
351 395 const QRectF& rect = QRectF(QPoint(0,0),event->newSize());
352 396 QGraphicsWidget::resizeEvent(event);
353 397 if(d_ptr->m_rect != rect) {
354 398 d_ptr->m_rect = rect;
355 399 d_ptr->updateLayout();
356 400 }
357 401 }
358 402
359 403 /*!
360 404 \internal \a event see QGraphicsWidget for details
361 405 */
362 406 void QLegend::hideEvent(QHideEvent *event)
363 407 {
364 408 QGraphicsWidget::hideEvent(event);
365 409 setEnabled(false);
366 410 d_ptr->updateLayout();
367 411 }
368 412
369 413 /*!
370 414 \internal \a event see QGraphicsWidget for details
371 415 */
372 416 void QLegend::showEvent(QShowEvent *event)
373 417 {
374 418 QGraphicsWidget::showEvent(event);
375 419 setEnabled(true);
376 420 d_ptr->updateLayout();
377 421 }
378 422
379 423 qreal QLegend::minWidth() const
380 424 {
381 425 return d_ptr->m_minWidth;
382 426 }
383 427
384 428 qreal QLegend::minHeight() const
385 429 {
386 430 return d_ptr->m_minHeight;
387 431 }
388 432
389 433 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
390 434
391 435 QLegendPrivate::QLegendPrivate(ChartPresenter* presenter, QChart *chart, QLegend *q):
392 436 q_ptr(q),
393 437 m_presenter(presenter),
394 438 m_chart(chart),
395 439 m_markers(new QGraphicsItemGroup(q)),
396 440 m_alignment(Qt::AlignTop),
397 441 m_brush(QBrush()),
398 442 m_pen(QPen()),
443 m_labelPen(QPen(Qt::NoPen)),
444 m_labelBrush(QBrush()),
399 445 m_offsetX(0),
400 446 m_offsetY(0),
401 447 m_minWidth(0),
402 448 m_minHeight(0),
403 449 m_width(0),
404 450 m_height(0),
405 451 m_diameter(5),
406 452 m_attachedToChart(true),
407 453 m_backgroundVisible(false)
408 454 {
409 455
410 456 }
411 457
412 458 QLegendPrivate::~QLegendPrivate()
413 459 {
414 460
415 461 }
416 462
417 463 void QLegendPrivate::setOffset(qreal x, qreal y)
418 464 {
419 465 bool scrollHorizontal = true;
420 466 switch(m_alignment) {
421 467 case Qt::AlignTop:
422 468 case Qt::AlignBottom: {
423 469 scrollHorizontal = true;
424 470 break;
425 471 }
426 472 case Qt::AlignLeft:
427 473 case Qt::AlignRight: {
428 474 scrollHorizontal = false;
429 475 break;
430 476 }
431 477 }
432 478
433 479 // If detached, the scrolling direction is vertical instead of horizontal and vice versa.
434 480 if (!m_attachedToChart) {
435 481 scrollHorizontal = !scrollHorizontal;
436 482 }
437 483
438 484 // Limit offset between m_minOffset and m_maxOffset
439 485 if (scrollHorizontal) {
440 486 if(m_width<=m_rect.width()) return;
441 487
442 488 if (x != m_offsetX) {
443 489 m_offsetX = qBound(m_minOffsetX, x, m_maxOffsetX);
444 490 m_markers->setPos(-m_offsetX,m_rect.top());
445 491 }
446 492 } else {
447 493 if(m_height<=m_rect.height()) return;
448 494
449 495 if (y != m_offsetY) {
450 496 m_offsetY = qBound(m_minOffsetY, y, m_maxOffsetY);
451 497 m_markers->setPos(m_rect.left(),-m_offsetY);
452 498 }
453 499 }
454 500 }
455 501
456 502 QPointF QLegendPrivate::offset() const
457 503 {
458 504 return QPointF(m_offsetX,m_offsetY);
459 505 }
460 506
461 507 void QLegendPrivate::updateLayout()
462 508 {
463 509 if (!m_attachedToChart) {
464 510 updateDetachedLayout();
465 511 return;
466 512 }
467 513
468 514 m_offsetX=0;
469 515 QList<QGraphicsItem *> items = m_markers->childItems();
470 516
471 517 if(items.isEmpty()) return;
472 518
473 519 m_minWidth=0;
474 520 m_minHeight=0;
475 521
476 522 switch(m_alignment) {
477 523
478 524 case Qt::AlignTop:
479 525 case Qt::AlignBottom: {
480 526 QPointF point = m_rect.topLeft();
481 527 m_width = 0;
482 528 foreach (QGraphicsItem *item, items) {
483 529 if (item->isVisible()) {
484 530 item->setPos(point.x(),m_rect.height()/2 -item->boundingRect().height()/2);
485 531 const QRectF& rect = item->boundingRect();
486 532 qreal w = rect.width();
487 533 m_minWidth=qMax(m_minWidth,w);
488 534 m_minHeight=qMax(m_minHeight,rect.height());
489 535 m_width+=w;
490 536 point.setX(point.x() + w);
491 537 }
492 538 }
493 539 if(m_width<m_rect.width()) {
494 540 m_markers->setPos(m_rect.width()/2-m_width/2,m_rect.top());
495 541 }
496 542 else {
497 543 m_markers->setPos(m_rect.topLeft());
498 544 }
499 545 m_height=m_minHeight;
500 546 }
501 547 break;
502 548 case Qt::AlignLeft:
503 549 case Qt::AlignRight: {
504 550 QPointF point = m_rect.topLeft();
505 551 m_height = 0;
506 552 foreach (QGraphicsItem *item, items) {
507 553 if (item->isVisible()) {
508 554 item->setPos(point);
509 555 const QRectF& rect = item->boundingRect();
510 556 qreal h = rect.height();
511 557 m_minWidth=qMax(m_minWidth,rect.width());
512 558 m_minHeight=qMax(m_minHeight,h);
513 559 m_height+=h;
514 560 point.setY(point.y() + h);
515 561 }
516 562 }
517 563 if(m_height<m_rect.height()) {
518 564 m_markers->setPos(m_rect.left(),m_rect.height()/2-m_height/2);
519 565 }
520 566 else {
521 567 m_markers->setPos(m_rect.topLeft());
522 568 }
523 569 m_width=m_minWidth;
524 570 }
525 571 break;
526 572 }
527 573
528 574 m_minOffsetX = 0;
529 575 m_minOffsetY = 0;
530 576 m_maxOffsetX = m_width - m_rect.width();
531 577 m_maxOffsetY = m_height - m_rect.height();
532 578
533 579 m_presenter->updateLayout();
534 580 }
535 581
536 582 void QLegendPrivate::updateDetachedLayout()
537 583 {
538 584 // Detached layout is different.
539 585 // In detached mode legend may have multiple rows and columns, so layout calculations
540 586 // differ a log from attached mode.
541 587 // Also the scrolling logic is bit different.
542 588 m_offsetX=0;
543 589 m_offsetY=0;
544 590 QList<QGraphicsItem *> items = m_markers->childItems();
545 591
546 592 if(items.isEmpty()) return;
547 593
548 594 m_minWidth = 0;
549 595 m_minHeight = 0;
550 596
551 597 switch (m_alignment) {
552 598 case Qt::AlignTop: {
553 599 QPointF point = m_rect.topLeft();
554 600 m_width = 0;
555 601 m_height = 0;
556 602 for (int i=0; i<items.count(); i++) {
557 603 QGraphicsItem *item = items.at(i);
558 604 if (item->isVisible()) {
559 605 const QRectF& rect = item->boundingRect();
560 606 qreal w = rect.width();
561 607 qreal h = rect.height();
562 608 m_minWidth = qMax(m_minWidth,w);
563 609 m_minHeight = qMax(m_minHeight,rect.height());
564 610 m_height = qMax(m_height,h);
565 611 item->setPos(point.x(),point.y());
566 612 point.setX(point.x() + w);
567 613 if (point.x() + w > m_rect.topLeft().x() + m_rect.width()) {
568 614 // Next item would go off rect.
569 615 point.setX(m_rect.topLeft().x());
570 616 point.setY(point.y() + h);
571 617 if (i+1 < items.count()) {
572 618 m_height += h;
573 619 }
574 620 }
575 621 }
576 622 }
577 623 m_markers->setPos(m_rect.topLeft());
578 624 m_width = m_minWidth;
579 625
580 626 m_minOffsetX = 0;
581 627 m_minOffsetY = 0;
582 628 m_maxOffsetX = m_width - m_rect.width();
583 629 m_maxOffsetY = m_height - m_rect.height();
584 630 }
585 631 break;
586 632 case Qt::AlignBottom: {
587 633 QPointF point = m_rect.bottomLeft();
588 634 m_width = 0;
589 635 m_height = 0;
590 636 for (int i=0; i<items.count(); i++) {
591 637 QGraphicsItem *item = items.at(i);
592 638 if (item->isVisible()) {
593 639 const QRectF& rect = item->boundingRect();
594 640 qreal w = rect.width();
595 641 qreal h = rect.height();
596 642 m_minWidth = qMax(m_minWidth,w);
597 643 m_minHeight = qMax(m_minHeight,rect.height());
598 644 m_height = qMax(m_height,h);
599 645 item->setPos(point.x(),point.y() - h);
600 646 point.setX(point.x() + w);
601 647 if (point.x() + w > m_rect.bottomLeft().x() + m_rect.width()) {
602 648 // Next item would go off rect.
603 649 point.setX(m_rect.bottomLeft().x());
604 650 point.setY(point.y() - h);
605 651 if (i+1 < items.count()) {
606 652 m_height += h;
607 653 }
608 654 }
609 655 }
610 656 }
611 657 m_markers->setPos(m_rect.topLeft());
612 658 m_width = m_minWidth;
613 659
614 660 m_minOffsetX = 0;
615 661 m_minOffsetY = qMin(m_rect.topLeft().y(), m_rect.topLeft().y() - m_height + m_rect.height());
616 662 m_maxOffsetX = m_width - m_rect.width();
617 663 m_maxOffsetY = 0;
618 664 }
619 665 break;
620 666 case Qt::AlignLeft: {
621 667 QPointF point = m_rect.topLeft();
622 668 m_width = 0;
623 669 m_height = 0;
624 670 qreal maxWidth = 0;
625 671 for (int i=0; i<items.count(); i++) {
626 672 QGraphicsItem *item = items.at(i);
627 673 if (item->isVisible()) {
628 674 const QRectF& rect = item->boundingRect();
629 675 qreal w = rect.width();
630 676 qreal h = rect.height();
631 677 m_minWidth = qMax(m_minWidth,rect.width());
632 678 m_minHeight = qMax(m_minHeight,h);
633 679 maxWidth = qMax(maxWidth,w);
634 680 item->setPos(point.x(),point.y());
635 681 point.setY(point.y() + h);
636 682 if (point.y() + h > m_rect.topLeft().y() + m_rect.height()) {
637 683 // Next item would go off rect.
638 684 point.setX(point.x() + maxWidth);
639 685 point.setY(m_rect.topLeft().y());
640 686 if (i+1 < items.count()) {
641 687 m_width += maxWidth;
642 688 maxWidth = 0;
643 689 }
644 690 }
645 691 }
646 692 }
647 693 m_width += maxWidth;
648 694 m_markers->setPos(m_rect.topLeft());
649 695 m_height = m_minHeight;
650 696
651 697 m_minOffsetX = 0;
652 698 m_minOffsetY = 0;
653 699 m_maxOffsetX = m_width - m_rect.width();
654 700 m_maxOffsetY = m_height - m_rect.height();
655 701 }
656 702 break;
657 703 case Qt::AlignRight: {
658 704 QPointF point = m_rect.topRight();
659 705 m_width = 0;
660 706 m_height = 0;
661 707 qreal maxWidth = 0;
662 708 for (int i=0; i<items.count(); i++) {
663 709 QGraphicsItem *item = items.at(i);
664 710 if (item->isVisible()) {
665 711 const QRectF& rect = item->boundingRect();
666 712 qreal w = rect.width();
667 713 qreal h = rect.height();
668 714 m_minWidth = qMax(m_minWidth,rect.width());
669 715 m_minHeight = qMax(m_minHeight,h);
670 716 maxWidth = qMax(maxWidth,w);
671 717 item->setPos(point.x() - w,point.y());
672 718 point.setY(point.y() + h);
673 719 if (point.y() + h > m_rect.topLeft().y() + m_rect.height()) {
674 720 // Next item would go off rect.
675 721 point.setX(point.x() - maxWidth);
676 722 point.setY(m_rect.topLeft().y());
677 723 if (i+1 < items.count()) {
678 724 m_width += maxWidth;
679 725 maxWidth = 0;
680 726 }
681 727 }
682 728 }
683 729 }
684 730 m_width += maxWidth;
685 731 m_markers->setPos(m_rect.topLeft());
686 732 m_height = m_minHeight;
687 733
688 734 m_minOffsetX = qMin(m_rect.topLeft().x(), m_rect.topLeft().x() - m_width + m_rect.width());
689 735 m_minOffsetY = 0;
690 736 m_maxOffsetX = 0;
691 737 m_maxOffsetY = m_height - m_rect.height();
692 738 }
693 739 break;
694 740 default:
695 741 break;
696 742 }
697 743 }
698 744
699 745 void QLegendPrivate::attachToChart()
700 746 {
701 747 m_attachedToChart = true;
702 748 q_ptr->setParent(m_chart);
703 749 }
704 750
705 751 int QLegendPrivate::roundness(qreal size)
706 752 {
707 753 return 100*m_diameter/int(size);
708 754 }
709 755
710 756 void QLegendPrivate::setFont(const QFont &font)
711 757 {
712 758 m_font = font;
713 759 QList<QGraphicsItem *> items = m_markers->childItems();
714 760
715 761 foreach (QGraphicsItem *markers, items) {
716 762 LegendMarker *marker = static_cast<LegendMarker*>(markers);
717 763 marker->setFont(m_font);
718 764 }
719 765 updateLayout();
720 766 }
721 767
768 void QLegendPrivate::setLabelPen(const QPen &pen)
769 {
770 m_labelPen = pen;
771 QList<QGraphicsItem *> items = m_markers->childItems();
772
773 foreach (QGraphicsItem *markers, items) {
774 LegendMarker *marker = static_cast<LegendMarker*>(markers);
775 marker->setPen(m_labelPen);
776 }
777 updateLayout();
778 }
779
780 void QLegendPrivate::setLabelBrush(const QBrush &brush)
781 {
782 m_labelBrush = brush;
783 QList<QGraphicsItem *> items = m_markers->childItems();
784
785 foreach (QGraphicsItem *markers, items) {
786 LegendMarker *marker = static_cast<LegendMarker*>(markers);
787 marker->setLabelBrush(m_labelBrush);
788 }
789 updateLayout();
790 }
791
722 792 void QLegendPrivate::handleSeriesAdded(QAbstractSeries *series, Domain *domain)
723 793 {
724 794 Q_UNUSED(domain)
725 795
726 796 QList<LegendMarker*> markers = series->d_ptr->createLegendMarker(q_ptr);
727 797 foreach(LegendMarker* marker, markers) {
728 798 marker->setFont(m_font);
799 marker->setLabelPen(m_labelPen);
800 marker->setLabelBrush(m_labelBrush);
729 801 m_markers->addToGroup(marker);
730 802 }
731 803
732 804 QObject::connect(series, SIGNAL(visibleChanged()), this, SLOT(handleSeriesVisibleChanged()));
733 805
734 806 if(series->type() == QAbstractSeries::SeriesTypePie) {
735 807 QPieSeries *pieSeries = static_cast<QPieSeries *>(series);
736 808 QObject::connect(pieSeries, SIGNAL(added(QList<QPieSlice*>)), this, SLOT(handleUpdatePieSeries()));
737 809 QObject::connect(pieSeries, SIGNAL(removed(QList<QPieSlice*>)), this, SLOT(handleUpdatePieSeries()));
738 810 }
739 811
740 812 updateLayout();
741 813 }
742 814
743 815 void QLegendPrivate::handleSeriesRemoved(QAbstractSeries *series)
744 816 {
745 817 QList<QGraphicsItem *> items = m_markers->childItems();
746 818
747 819 foreach (QGraphicsItem *markers, items) {
748 820 LegendMarker *marker = static_cast<LegendMarker*>(markers);
749 821 if (marker->series() == series) {
750 822 delete marker;
751 823 }
752 824 }
753 825
754 826 if(series->type() == QAbstractSeries::SeriesTypePie)
755 827 {
756 828 QPieSeries *pieSeries = static_cast<QPieSeries *>(series);
757 829 QObject::disconnect(pieSeries, SIGNAL(added(QList<QPieSlice*>)), this, SLOT(handleUpdatePieSeries()));
758 830 QObject::disconnect(pieSeries, SIGNAL(removed(QList<QPieSlice*>)), this, SLOT(handleUpdatePieSeries()));
759 831 }
760 832
761 833 updateLayout();
762 834 }
763 835
764 836 void QLegendPrivate::handleSeriesUpdated(QAbstractSeries *series)
765 837 {
766 838 // TODO: find out which markers are are added or removed. Update them
767 839 // TODO: better implementation
768 840 handleSeriesRemoved(series);
769 841 Domain domain;
770 842 handleSeriesAdded(series, &domain);
771 843 }
772 844
773 845 void QLegendPrivate::handleUpdatePieSeries()
774 846 {
775 847 //TODO: reimplement to be optimal
776 848 QPieSeries* series = qobject_cast<QPieSeries *> (sender());
777 849 Q_ASSERT(series);
778 850 handleSeriesRemoved(series);
779 851 handleSeriesAdded(series, 0);
780 852 }
781 853
782 854 void QLegendPrivate::handleSeriesVisibleChanged()
783 855 {
784 856 QAbstractSeries* series = qobject_cast<QAbstractSeries *> (sender());
785 857 QList<QGraphicsItem *> items = m_markers->childItems();
786 858
787 859 foreach (QGraphicsItem *markers, items) {
788 860 LegendMarker *marker = static_cast<LegendMarker*>(markers);
789 861 if (marker->series() == series) {
790 862 marker->setVisible(!marker->isVisible());
791 863 }
792 864 }
793 865
794 866 updateLayout();
795 867 }
796 868
797 869
798 870 #include "moc_qlegend.cpp"
799 871 #include "moc_qlegend_p.cpp"
800 872
801 873 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,106 +1,121
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 #ifndef QLEGEND_H
22 22 #define QLEGEND_H
23 23
24 24 #include <QChartGlobal>
25 25 #include <QGraphicsWidget>
26 26 #include <QPen>
27 27 #include <QBrush>
28 28
29 29 QTCOMMERCIALCHART_BEGIN_NAMESPACE
30 30
31 31 class Domain;
32 32 class LegendMarker;
33 33 class QPieSlice;
34 34 class QXYSeries;
35 35 class QBarSet;
36 36 class QBarSeries;
37 37 class QPieSeries;
38 38 class QAreaSeries;
39 39 class LegendScrollButton;
40 40 class QChart;
41 41 class QLegendPrivate;
42 42
43 43 class QTCOMMERCIALCHART_EXPORT QLegend : public QGraphicsWidget
44 44 {
45 45 Q_OBJECT
46 46 Q_PROPERTY(Qt::Alignment alignment READ alignment WRITE setAlignment)
47 47 Q_PROPERTY(bool backgroundVisible READ isBackgroundVisible WRITE setBackgroundVisible NOTIFY backgroundVisibleChanged)
48 48 Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
49 49 Q_PROPERTY(QColor borderColor READ borderColor WRITE setBorderColor NOTIFY borderColorChanged)
50 50 Q_PROPERTY(QFont font READ font WRITE setFont NOTIFY fontChanged)
51 Q_PROPERTY(QColor labelColor READ labelColor WRITE setLabelColor NOTIFY labelColorChanged)
52 // TODO?
53 // Q_PROPERTY(QColor labelBorderColor READ labelBorderColor WRITE setLabelBorderColor NOTIFY labelBorderColorChanged)
51 54
52 55 private:
53 56 explicit QLegend(QChart *chart);
54 57
55 58 public:
56 59 ~QLegend();
57 60
58 61 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
59 62 QRectF boundingRect() const;
60 63
61 64 void setBrush(const QBrush &brush);
62 65 QBrush brush() const;
63 66 void setColor(QColor color);
64 67 QColor color();
65 68
66 69 void setPen(const QPen &pen);
67 70 QPen pen() const;
68 71 void setBorderColor(QColor color);
69 72 QColor borderColor();
70 73
71 74 void setFont(const QFont &font);
72 75 QFont font() const;
76 void setLabelPen(const QPen &pen);
77 QPen labelPen() const;
78 void setLabelBrush(const QBrush &brush);
79 QBrush labelBrush() const;
80
81 void setLabelColor(QColor color);
82 QColor labelColor() const;
73 83
74 84 void setAlignment(Qt::Alignment alignment);
75 85 Qt::Alignment alignment() const;
76 86
77 87 void detachFromChart();
78 88 void attachToChart();
79 89 bool isAttachedToChart();
80 90
81 91 qreal minWidth() const;
82 92 qreal minHeight() const;
83 93
84 94 void setBackgroundVisible(bool visible = true);
85 95 bool isBackgroundVisible() const;
86 96
87 97 protected:
88 98 void resizeEvent(QGraphicsSceneResizeEvent *event);
89 99 void hideEvent(QHideEvent *event);
90 100 void showEvent(QShowEvent *event);
91 101
92 102 Q_SIGNALS:
93 103 void backgroundVisibleChanged(bool visible);
94 104 void colorChanged(QColor color);
95 105 void borderColorChanged(QColor color);
96 106 void fontChanged(QFont font);
107 void labelPenChanged(QPen pen);
108 void labelBrushChanged(QBrush brush);
109 void labelColorChanged(QColor color);
110 // TODO?
111 // void labelBorderColorChanged(QColor color);
97 112
98 113 private:
99 114 QScopedPointer<QLegendPrivate> d_ptr;
100 115 Q_DISABLE_COPY(QLegend)
101 116 friend class LegendScroller;
102 117 };
103 118
104 119 QTCOMMERCIALCHART_END_NAMESPACE
105 120
106 121 #endif // QLEGEND_H
@@ -1,93 +1,97
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 QLEGEND_P_H
31 31 #define QLEGEND_P_H
32 32
33 33 #include "qlegend.h"
34 34
35 35 QTCOMMERCIALCHART_BEGIN_NAMESPACE
36 36
37 37 class QChart;
38 38 class ChartPresenter;
39 39 class QAbstractSeries;
40 40
41 41 class QLegendPrivate : public QObject
42 42 {
43 43 Q_OBJECT
44 44 public:
45 45 QLegendPrivate(ChartPresenter *presenter, QChart *chart, QLegend *q);
46 46 ~QLegendPrivate();
47 47
48 48 void setOffset(qreal x, qreal y);
49 49 QPointF offset() const;
50 50 void updateLayout();
51 51 void updateDetachedLayout();
52 52 void attachToChart();
53 53 int roundness(qreal size);
54 54 void setFont(const QFont &font);
55 void setLabelPen(const QPen &pen);
56 void setLabelBrush(const QBrush &brush);
55 57
56 58 public Q_SLOTS:
57 59 void handleSeriesAdded(QAbstractSeries *series, Domain *domain);
58 60 void handleSeriesRemoved(QAbstractSeries *series);
59 61 void handleSeriesUpdated(QAbstractSeries *series);
60 62 void handleUpdatePieSeries(); //TODO remove this function
61 63 void handleSeriesVisibleChanged();
62 64
63 65 private:
64 66 QLegend *q_ptr;
65 67 ChartPresenter *m_presenter;
66 68 QChart* m_chart;
67 69 QGraphicsItemGroup* m_markers;
68 70 Qt::Alignment m_alignment;
69 71 QBrush m_brush;
70 72 QPen m_pen;
71 73 QFont m_font;
74 QPen m_labelPen;
75 QBrush m_labelBrush;
72 76 QRectF m_rect;
73 77 qreal m_offsetX;
74 78 qreal m_offsetY;
75 79 qreal m_minOffsetX;
76 80 qreal m_minOffsetY;
77 81 qreal m_maxOffsetX;
78 82 qreal m_maxOffsetY;
79 83 qreal m_minWidth;
80 84 qreal m_minHeight;
81 85 qreal m_width;
82 86 qreal m_height;
83 87 qreal m_diameter;
84 88 bool m_attachedToChart;
85 89 bool m_backgroundVisible;
86 90
87 91 friend class QLegend;
88 92
89 93 };
90 94
91 95 QTCOMMERCIALCHART_END_NAMESPACE
92 96
93 97 #endif
General Comments 0
You need to be logged in to leave comments. Login now