##// END OF EJS Templates
Warnings treated as errors; fixed one
Tero Ahola -
r647:adb69112ecad
parent child
Show More
@@ -1,491 +1,492
1 1 #include "qchartglobal.h"
2 2 #include "qlegend.h"
3 3 #include "qseries.h"
4 4 #include "legendmarker_p.h"
5 5 #include "qxyseries.h"
6 6 #include "qlineseries.h"
7 7 #include "qareaseries.h"
8 8 #include "qscatterseries.h"
9 9 #include "qsplineseries.h"
10 10 #include "qbarseries.h"
11 11 #include "qstackedbarseries.h"
12 12 #include "qpercentbarseries.h"
13 13 #include "qbarset.h"
14 14 #include "qpieseries.h"
15 15 #include "qpieslice.h"
16 16 #include "chartpresenter_p.h"
17 17 #include <QPainter>
18 18 #include <QPen>
19 19
20 20 #include <QGraphicsSceneEvent>
21 21
22 22 QTCOMMERCIALCHART_BEGIN_NAMESPACE
23 23
24 24 QLegend::QLegend(QGraphicsItem *parent)
25 25 : QGraphicsObject(parent)
26 26 ,mPos(0,0)
27 27 ,mSize(0,0)
28 28 ,mMinimumSize(50,20) // TODO: magic numbers
29 29 ,mMaximumSize(150,100)
30 30 ,m_brush(Qt::darkGray) // TODO: from theme?
31 31 ,mPreferredLayout(QLegend::PreferredLayoutVertical)
32 32 {
33 33 // setVisible(false);
34 34 setZValue(ChartPresenter::LegendZValue);
35 35 }
36 36
37 37 void QLegend::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
38 38 {
39 39 Q_UNUSED(option)
40 40 Q_UNUSED(widget)
41 41
42 42 painter->setOpacity(0.5);
43 43 painter->setPen(m_pen);
44 44 painter->setBrush(m_brush);
45 45 painter->drawRect(boundingRect());
46 46 }
47 47
48 48 QRectF QLegend::boundingRect() const
49 49 {
50 50 return QRectF(mPos,mSize);
51 51 }
52 52
53 53 void QLegend::setBrush(const QBrush& brush)
54 54 {
55 55 if(m_brush!=brush){
56 56 m_brush = brush;
57 57 update();
58 58 }
59 59 }
60 60
61 61 QBrush QLegend::brush() const
62 62 {
63 63 return m_brush;
64 64 }
65 65
66 66 void QLegend::setPen(const QPen& pen)
67 67 {
68 68 if(m_pen!=pen){
69 69 m_pen = pen;
70 70 update();
71 71 }
72 72 }
73 73
74 74 QPen QLegend::pen() const
75 75 {
76 76 return m_pen;
77 77 }
78 78
79 79 void QLegend::setPreferredLayout(QLegend::PreferredLayout preferred)
80 80 {
81 81 mPreferredLayout = preferred;
82 82 layoutChanged();
83 83 }
84 84
85 85 QSizeF QLegend::maximumSize() const
86 86 {
87 87 return mMaximumSize;
88 88 }
89 89
90 90 void QLegend::setMaximumSize(const QSizeF size)
91 91 {
92 92 mMaximumSize = size;
93 93 }
94 94
95 95 void QLegend::setSize(const QSizeF size)
96 96 {
97 97 mSize = size;
98 98 if (mSize.width() > mMaximumSize.width()) {
99 99 mSize.setWidth(mMaximumSize.width());
100 100 }
101 101 if (mSize.height() > mMaximumSize.height()) {
102 102 mSize.setHeight(mMaximumSize.height());
103 103 }
104 104 }
105 105
106 106 void QLegend::setPos(const QPointF &pos)
107 107 {
108 108 mPos = pos;
109 109 }
110 110
111 111 void QLegend::handleSeriesAdded(QSeries* series, Domain* domain)
112 112 {
113 113 Q_UNUSED(domain)
114 114
115 115 // mSeriesList.append(series);
116 116 createMarkers(series);
117 117 connectSeries(series);
118 118 layoutChanged();
119 119 }
120 120
121 121 void QLegend::handleSeriesRemoved(QSeries* series)
122 122 {
123 123 disconnectSeries(series);
124 124
125 125 if (series->type() == QSeries::SeriesTypeArea)
126 126 {
127 127 // This is special case. Area series has upper and lower series, which each have markers
128 128 QAreaSeries* s = static_cast<QAreaSeries*> (series);
129 129 deleteMarkers(s->upperSeries());
130 130 deleteMarkers(s->lowerSeries());
131 131 } else {
132 132 deleteMarkers(series);
133 133 }
134 134
135 135 // mSeriesList.removeOne(series);
136 136 layoutChanged();
137 137 }
138 138
139 139 void QLegend::handleAdded(QList<QPieSlice*> slices)
140 140 {
141 141 QPieSeries* series = static_cast<QPieSeries*> (sender());
142 142 foreach(QPieSlice* s, slices) {
143 143 LegendMarker* marker = new LegendMarker(series,s,this);
144 144 marker->setName(s->label());
145 145 marker->setBrush(s->sliceBrush());
146 146 connect(marker,SIGNAL(clicked(QPieSlice*,Qt::MouseButton)),this,SIGNAL(clicked(QPieSlice*,Qt::MouseButton)));
147 147 connect(s,SIGNAL(changed()),marker,SLOT(changed()));
148 148 connect(s,SIGNAL(destroyed()),marker,SLOT(deleteLater()));
149 149 connect(marker,SIGNAL(destroyed()),this,SLOT(handleMarkerDestroyed()));
150 150 mMarkers.append(marker);
151 151 childItems().append(marker);
152 152 }
153 153 layoutChanged();
154 154 }
155 155
156 156 void QLegend::handleRemoved(QList<QPieSlice *> slices)
157 157 {
158 Q_UNUSED(slices)
158 159 // Propably no need to listen for this, since removed slices are deleted and we listen destroyed signal
159 160 // qDebug() << "QLegend::handleRemoved(QList<QPieSlice*> slices) count:" << slices.count();
160 161 }
161 162
162 163
163 164 void QLegend::handleMarkerDestroyed()
164 165 {
165 166 // TODO: what if more than one markers are destroyed and we update layout after first one?
166 167 LegendMarker* m = static_cast<LegendMarker*> (sender());
167 168 mMarkers.removeOne(m);
168 169 layoutChanged();
169 170 }
170 171
171 172 void QLegend::connectSeries(QSeries *series)
172 173 {
173 174 // Connect relevant signals from series
174 175 switch (series->type())
175 176 {
176 177 case QSeries::SeriesTypeLine: {
177 178 // QLineSeries* lineSeries = static_cast<QLineSeries*>(series);
178 179 break;
179 180 }
180 181 case QSeries::SeriesTypeArea: {
181 182 // QAreaSeries* areaSeries = static_cast<QAreaSeries*>(series);
182 183 break;
183 184 }
184 185 case QSeries::SeriesTypeBar: {
185 186 // QBarSeries* barSeries = static_cast<QBarSeries*>(series);
186 187 break;
187 188 }
188 189 case QSeries::SeriesTypeStackedBar: {
189 190 // QStackedBarSeries* stackedBarSeries = static_cast<QStackedBarSeries*>(series);
190 191 break;
191 192 }
192 193 case QSeries::SeriesTypePercentBar: {
193 194 // QPercentBarSeries* percentBarSeries = static_cast<QPercentBarSeries*>(series);
194 195 break;
195 196 }
196 197 case QSeries::SeriesTypeScatter: {
197 198 // QScatterSeries *scatterSeries = static_cast<QScatterSeries *>(series);
198 199 break;
199 200 }
200 201 case QSeries::SeriesTypePie: {
201 202 QPieSeries *pieSeries = static_cast<QPieSeries *>(series);
202 203 connect(pieSeries,SIGNAL(added(QList<QPieSlice*>)),this,SLOT(handleAdded(QList<QPieSlice*>)));
203 204 // connect(pieSeries,SIGNAL(removed(QList<QPieSlice*>)),this,SLOT(handleRemoved(QList<QPieSlice*>)));
204 205 break;
205 206 }
206 207 case QSeries::SeriesTypeSpline: {
207 208 // QSplineSeries* splineSeries = static_cast<QSplineSeries*>(series);
208 209 break;
209 210 }
210 211 default: {
211 212 qDebug()<< "QLegend::connectSeries" << series->type() << "not implemented.";
212 213 break;
213 214 }
214 215 }
215 216 }
216 217
217 218 void QLegend::disconnectSeries(QSeries *series)
218 219 {
219 220 // Connect relevant signals from series
220 221 switch (series->type())
221 222 {
222 223 case QSeries::SeriesTypeLine: {
223 224 // QLineSeries* lineSeries = static_cast<QLineSeries*>(series);
224 225 break;
225 226 }
226 227 case QSeries::SeriesTypeArea: {
227 228 // QAreaSeries* areaSeries = static_cast<QAreaSeries*>(series);
228 229 break;
229 230 }
230 231 case QSeries::SeriesTypeBar: {
231 232 // QBarSeries* barSeries = static_cast<QBarSeries*>(series);
232 233 break;
233 234 }
234 235 case QSeries::SeriesTypeStackedBar: {
235 236 // QStackedBarSeries* stackedBarSeries = static_cast<QStackedBarSeries*>(series);
236 237 break;
237 238 }
238 239 case QSeries::SeriesTypePercentBar: {
239 240 // QPercentBarSeries* percentBarSeries = static_cast<QPercentBarSeries*>(series);
240 241 break;
241 242 }
242 243 case QSeries::SeriesTypeScatter: {
243 244 // QScatterSeries *scatterSeries = static_cast<QScatterSeries *>(series);
244 245 break;
245 246 }
246 247 case QSeries::SeriesTypePie: {
247 248 QPieSeries *pieSeries = static_cast<QPieSeries *>(series);
248 249 disconnect(pieSeries,SIGNAL(added(QList<QPieSlice*>)),this,SLOT(handleAdded(QList<QPieSlice*>)));
249 250 // disconnect(pieSeries,SIGNAL(removed(QList<QPieSlice*>)),this,SLOT(handleRemoved(QList<QPieSlice*>)));
250 251 break;
251 252 }
252 253 case QSeries::SeriesTypeSpline: {
253 254 // QSplineSeries* splineSeries = static_cast<QSplineSeries*>(series);
254 255 break;
255 256 }
256 257 default: {
257 258 qDebug()<< "QLegend::disconnectSeries" << series->type() << "not implemented.";
258 259 break;
259 260 }
260 261 }
261 262 }
262 263
263 264 void QLegend::createMarkers(QSeries *series)
264 265 {
265 266 switch (series->type())
266 267 {
267 268 case QSeries::SeriesTypeLine: {
268 269 QLineSeries* lineSeries = static_cast<QLineSeries*>(series);
269 270 appendMarkers(lineSeries);
270 271 break;
271 272 }
272 273 case QSeries::SeriesTypeArea: {
273 274 QAreaSeries* areaSeries = static_cast<QAreaSeries*>(series);
274 275 appendMarkers(areaSeries->upperSeries());
275 276 if(areaSeries->lowerSeries())
276 277 appendMarkers(areaSeries->lowerSeries());
277 278 break;
278 279 }
279 280
280 281 case QSeries::SeriesTypeBar: {
281 282 QBarSeries* barSeries = static_cast<QBarSeries*>(series);
282 283 appendMarkers(barSeries);
283 284 break;
284 285 }
285 286
286 287 case QSeries::SeriesTypeStackedBar: {
287 288 QStackedBarSeries* stackedBarSeries = static_cast<QStackedBarSeries*>(series);
288 289 appendMarkers(stackedBarSeries);
289 290 break;
290 291 }
291 292
292 293 case QSeries::SeriesTypePercentBar: {
293 294 QPercentBarSeries* percentBarSeries = static_cast<QPercentBarSeries*>(series);
294 295 appendMarkers(percentBarSeries);
295 296 break;
296 297 }
297 298
298 299 case QSeries::SeriesTypeScatter: {
299 300 QScatterSeries *scatterSeries = static_cast<QScatterSeries *>(series);
300 301 appendMarkers(scatterSeries);
301 302 break;
302 303 }
303 304
304 305 case QSeries::SeriesTypePie: {
305 306 QPieSeries *pieSeries = static_cast<QPieSeries *>(series);
306 307 appendMarkers(pieSeries);
307 308 break;
308 309 }
309 310
310 311 case QSeries::SeriesTypeSpline: {
311 312 QSplineSeries* splineSeries = static_cast<QSplineSeries*>(series);
312 313 appendMarkers(splineSeries);
313 314 break;
314 315 }
315 316 default: {
316 317 qDebug()<< "QLegend::createMarkers" << series->type() << "not implemented.";
317 318 break;
318 319 }
319 320 }
320 321 }
321 322
322 323 void QLegend::appendMarkers(QXYSeries* series)
323 324 {
324 325 LegendMarker* marker = new LegendMarker(series,this);
325 326 marker->setName(series->name());
326 327 marker->setBrush(series->brush());
327 328 connect(marker,SIGNAL(clicked(QSeries*,Qt::MouseButton)),this,SIGNAL(clicked(QSeries*,Qt::MouseButton)));
328 329 connect(marker,SIGNAL(destroyed()),this,SLOT(handleMarkerDestroyed()));
329 330 mMarkers.append(marker);
330 331 childItems().append(marker);
331 332 }
332 333
333 334 void QLegend::appendMarkers(QBarSeries *series)
334 335 {
335 336 foreach(QBarSet* s, series->barSets()) {
336 337 LegendMarker* marker = new LegendMarker(series,s,this);
337 338 marker->setName(s->name());
338 339 marker->setBrush(s->brush());
339 340 connect(marker,SIGNAL(clicked(QBarSet*,Qt::MouseButton)),this,SIGNAL(clicked(QBarSet*,Qt::MouseButton)));
340 341 connect(s,SIGNAL(changed()),marker,SLOT(changed()));
341 342 connect(marker,SIGNAL(destroyed()),this,SLOT(handleMarkerDestroyed()));
342 343 mMarkers.append(marker);
343 344 childItems().append(marker);
344 345 }
345 346 }
346 347
347 348 void QLegend::appendMarkers(QPieSeries *series)
348 349 {
349 350 foreach(QPieSlice* s, series->slices()) {
350 351 LegendMarker* marker = new LegendMarker(series,s,this);
351 352 marker->setName(s->label());
352 353 marker->setBrush(s->sliceBrush());
353 354 connect(marker,SIGNAL(clicked(QPieSlice*,Qt::MouseButton)),this,SIGNAL(clicked(QPieSlice*,Qt::MouseButton)));
354 355 connect(s,SIGNAL(changed()),marker,SLOT(changed()));
355 356 connect(s,SIGNAL(destroyed()),marker,SLOT(deleteLater()));
356 357 connect(marker,SIGNAL(destroyed()),this,SLOT(handleMarkerDestroyed()));
357 358 mMarkers.append(marker);
358 359 childItems().append(marker);
359 360 }
360 361 }
361 362
362 363 void QLegend::deleteMarkers(QSeries *series)
363 364 {
364 365 // Search all markers that belong to given series and delete them.
365 366 foreach (LegendMarker *m, mMarkers) {
366 367 if (m->series() == series) {
367 368 mMarkers.removeOne(m);
368 369 delete m;
369 370 }
370 371 }
371 372 }
372 373
373 374 void QLegend::layoutChanged()
374 375 {
375 376 // Calculate layout for markers and text
376 377 qDebug() << "Marker count:" << mMarkers.count();
377 378 if (mMarkers.count() <= 0) {
378 379 // Nothing to do
379 380 return;
380 381 }
381 382
382 383 // Find out widest item.
383 384 qreal itemMaxWidth = 0;
384 385 qreal itemMaxHeight = 0;
385 386 foreach (LegendMarker* m, mMarkers) {
386 387 if (m->boundingRect().width() > itemMaxWidth) {
387 388 itemMaxWidth = m->boundingRect().width();
388 389 }
389 390 if (m->boundingRect().height() > itemMaxHeight) {
390 391 itemMaxHeight = m->boundingRect().height();
391 392 }
392 393 }
393 394
394 395 int maxHorizontalItems = boundingRect().width() / itemMaxWidth;
395 396 int maxVerticalItems = boundingRect().height() / itemMaxHeight;
396 397
397 398 if (mMarkers.count() > maxHorizontalItems * maxVerticalItems) {
398 399 // TODO: overlapping layout
399 400 qDebug() << "Warning. Not enough space to layout all legend items properly.";
400 401 }
401 402
402 403 qreal margin = 5;
403 404 qreal totalWidth = 0;
404 405 qreal totalHeight = 0;
405 406 switch (mPreferredLayout)
406 407 {
407 408 case QLegend::PreferredLayoutHorizontal: {
408 409 /*
409 410 qreal xStep = mMaximumSize.width() / (mMarkers.count()+1);
410 411 if (xStep > itemMaxWidth) {
411 412 xStep = itemMaxWidth;
412 413 }
413 414 qreal yStep = mMaximumSize.height() / (mMarkers.count()+1);
414 415 if (yStep > itemMaxHeight) {
415 416 yStep = itemMaxHeight;
416 417 }*/
417 418 qreal xStep = itemMaxWidth;
418 419 qreal yStep = itemMaxHeight;
419 420 qreal x = mPos.x() + margin;
420 421 qreal y = mPos.y() + margin;
421 422 int row = 1;
422 423 int column = 0;
423 424 int maxRows = 1;
424 425 int maxColumns = 1;
425 426 foreach (LegendMarker* m, mMarkers) {
426 427 maxRows = row;
427 428 m->setPos(x,y);
428 429 x += xStep;
429 430 column++;
430 431 if (column > maxColumns) {
431 432 maxColumns = column;
432 433 }
433 434 if ((x + itemMaxWidth + margin*2) > (mPos.x() + mMaximumSize.width())) {
434 435 x = mPos.x() + margin;
435 436 y += yStep;
436 437 row++;
437 438 column = 0;
438 439 }
439 440 }
440 441 totalWidth = maxColumns * itemMaxWidth + margin * 2;
441 442 totalHeight = maxRows * itemMaxHeight + margin * 2;
442 443 break;
443 444 }
444 445 case QLegend::PreferredLayoutVertical: {
445 446 /*
446 447 qreal xStep = mMaximumSize.width() / (mMarkers.count()+1);
447 448 if (xStep > itemMaxWidth) {
448 449 xStep = itemMaxWidth;
449 450 }
450 451 qreal yStep = mMaximumSize.height() / (mMarkers.count()+1);
451 452 if (yStep > itemMaxHeight) {
452 453 yStep = itemMaxHeight;
453 454 }*/
454 455 qreal xStep = itemMaxWidth;
455 456 qreal yStep = itemMaxHeight;
456 457 qreal x = mPos.x() + margin;
457 458 qreal y = mPos.y() + margin;
458 459 int row = 0;
459 460 int column = 1;
460 461 int maxRows = 1;
461 462 int maxColumns = 1;
462 463 foreach (LegendMarker* m, mMarkers) {
463 464 maxColumns = column;
464 465 m->setPos(x,y);
465 466 y += yStep;
466 467 row++;
467 468 if (row > maxRows) {
468 469 maxRows = row;
469 470 }
470 471 if ((y + itemMaxHeight + margin*2) > (mPos.y() + mMaximumSize.height())) {
471 472 y = mPos.y() + margin;
472 473 x += xStep;
473 474 column++;
474 475 row = 0;
475 476 }
476 477 }
477 478 totalWidth = maxColumns * itemMaxWidth + margin * 2;
478 479 totalHeight = maxRows * itemMaxHeight + margin * 2;
479 480 break;
480 481 }
481 482 default: {
482 483 break;
483 484 }
484 485 }
485 486
486 487 mSize.setWidth(totalWidth);
487 488 mSize.setHeight(totalHeight);
488 489 }
489 490
490 491 #include "moc_qlegend.cpp"
491 492 QTCOMMERCIALCHART_END_NAMESPACE
General Comments 0
You need to be logged in to leave comments. Login now