##// END OF EJS Templates
fixed changed singal name in legend
sauimone -
r670:27d565e40e33
parent child
Show More
@@ -1,491 +1,491
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 layoutChanged();
94 94 }
95 95
96 96 void QLegend::setSize(const QSizeF size)
97 97 {
98 98 mSize = size;
99 99 if (mSize.width() > mMaximumSize.width()) {
100 100 mSize.setWidth(mMaximumSize.width());
101 101 }
102 102 if (mSize.height() > mMaximumSize.height()) {
103 103 mSize.setHeight(mMaximumSize.height());
104 104 }
105 105 }
106 106
107 107 void QLegend::setPos(const QPointF &pos)
108 108 {
109 109 mPos = pos;
110 110 layoutChanged();
111 111 }
112 112
113 113 void QLegend::handleSeriesAdded(QSeries* series, Domain* domain)
114 114 {
115 115 Q_UNUSED(domain)
116 116
117 117 createMarkers(series);
118 118 connectSeries(series);
119 119 layoutChanged();
120 120 }
121 121
122 122 void QLegend::handleSeriesRemoved(QSeries* series)
123 123 {
124 124 disconnectSeries(series);
125 125
126 126 if (series->type() == QSeries::SeriesTypeArea)
127 127 {
128 128 // This is special case. Area series has upper and lower series, which each have markers
129 129 QAreaSeries* s = static_cast<QAreaSeries*> (series);
130 130 deleteMarkers(s->upperSeries());
131 131 deleteMarkers(s->lowerSeries());
132 132 } else {
133 133 deleteMarkers(series);
134 134 }
135 135
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 158 Q_UNUSED(slices)
159 159 // Propably no need to listen for this, since removed slices are deleted and we listen destroyed signal
160 160 // qDebug() << "QLegend::handleRemoved(QList<QPieSlice*> slices) count:" << slices.count();
161 161 }
162 162
163 163
164 164 void QLegend::handleMarkerDestroyed()
165 165 {
166 166 // TODO: what if more than one markers are destroyed and we update layout after first one?
167 167 LegendMarker* m = static_cast<LegendMarker*> (sender());
168 168 mMarkers.removeOne(m);
169 169 layoutChanged();
170 170 }
171 171
172 172 void QLegend::connectSeries(QSeries *series)
173 173 {
174 174 // Connect relevant signals from series
175 175 switch (series->type())
176 176 {
177 177 case QSeries::SeriesTypeLine: {
178 178 // QLineSeries* lineSeries = static_cast<QLineSeries*>(series);
179 179 break;
180 180 }
181 181 case QSeries::SeriesTypeArea: {
182 182 // QAreaSeries* areaSeries = static_cast<QAreaSeries*>(series);
183 183 break;
184 184 }
185 185 case QSeries::SeriesTypeBar: {
186 186 // QBarSeries* barSeries = static_cast<QBarSeries*>(series);
187 187 break;
188 188 }
189 189 case QSeries::SeriesTypeStackedBar: {
190 190 // QStackedBarSeries* stackedBarSeries = static_cast<QStackedBarSeries*>(series);
191 191 break;
192 192 }
193 193 case QSeries::SeriesTypePercentBar: {
194 194 // QPercentBarSeries* percentBarSeries = static_cast<QPercentBarSeries*>(series);
195 195 break;
196 196 }
197 197 case QSeries::SeriesTypeScatter: {
198 198 // QScatterSeries *scatterSeries = static_cast<QScatterSeries *>(series);
199 199 break;
200 200 }
201 201 case QSeries::SeriesTypePie: {
202 202 QPieSeries *pieSeries = static_cast<QPieSeries *>(series);
203 203 connect(pieSeries,SIGNAL(added(QList<QPieSlice*>)),this,SLOT(handleAdded(QList<QPieSlice*>)));
204 204 // connect(pieSeries,SIGNAL(removed(QList<QPieSlice*>)),this,SLOT(handleRemoved(QList<QPieSlice*>)));
205 205 break;
206 206 }
207 207 case QSeries::SeriesTypeSpline: {
208 208 // QSplineSeries* splineSeries = static_cast<QSplineSeries*>(series);
209 209 break;
210 210 }
211 211 default: {
212 212 qDebug()<< "QLegend::connectSeries" << series->type() << "not implemented.";
213 213 break;
214 214 }
215 215 }
216 216 }
217 217
218 218 void QLegend::disconnectSeries(QSeries *series)
219 219 {
220 220 // Connect relevant signals from series
221 221 switch (series->type())
222 222 {
223 223 case QSeries::SeriesTypeLine: {
224 224 // QLineSeries* lineSeries = static_cast<QLineSeries*>(series);
225 225 break;
226 226 }
227 227 case QSeries::SeriesTypeArea: {
228 228 // QAreaSeries* areaSeries = static_cast<QAreaSeries*>(series);
229 229 break;
230 230 }
231 231 case QSeries::SeriesTypeBar: {
232 232 // QBarSeries* barSeries = static_cast<QBarSeries*>(series);
233 233 break;
234 234 }
235 235 case QSeries::SeriesTypeStackedBar: {
236 236 // QStackedBarSeries* stackedBarSeries = static_cast<QStackedBarSeries*>(series);
237 237 break;
238 238 }
239 239 case QSeries::SeriesTypePercentBar: {
240 240 // QPercentBarSeries* percentBarSeries = static_cast<QPercentBarSeries*>(series);
241 241 break;
242 242 }
243 243 case QSeries::SeriesTypeScatter: {
244 244 // QScatterSeries *scatterSeries = static_cast<QScatterSeries *>(series);
245 245 break;
246 246 }
247 247 case QSeries::SeriesTypePie: {
248 248 QPieSeries *pieSeries = static_cast<QPieSeries *>(series);
249 249 disconnect(pieSeries,SIGNAL(added(QList<QPieSlice*>)),this,SLOT(handleAdded(QList<QPieSlice*>)));
250 250 // disconnect(pieSeries,SIGNAL(removed(QList<QPieSlice*>)),this,SLOT(handleRemoved(QList<QPieSlice*>)));
251 251 break;
252 252 }
253 253 case QSeries::SeriesTypeSpline: {
254 254 // QSplineSeries* splineSeries = static_cast<QSplineSeries*>(series);
255 255 break;
256 256 }
257 257 default: {
258 258 qDebug()<< "QLegend::disconnectSeries" << series->type() << "not implemented.";
259 259 break;
260 260 }
261 261 }
262 262 }
263 263
264 264 void QLegend::createMarkers(QSeries *series)
265 265 {
266 266 switch (series->type())
267 267 {
268 268 case QSeries::SeriesTypeLine: {
269 269 QLineSeries* lineSeries = static_cast<QLineSeries*>(series);
270 270 appendMarkers(lineSeries);
271 271 break;
272 272 }
273 273 case QSeries::SeriesTypeArea: {
274 274 QAreaSeries* areaSeries = static_cast<QAreaSeries*>(series);
275 275 appendMarkers(areaSeries->upperSeries());
276 276 if(areaSeries->lowerSeries())
277 277 appendMarkers(areaSeries->lowerSeries());
278 278 break;
279 279 }
280 280
281 281 case QSeries::SeriesTypeBar: {
282 282 QBarSeries* barSeries = static_cast<QBarSeries*>(series);
283 283 appendMarkers(barSeries);
284 284 break;
285 285 }
286 286
287 287 case QSeries::SeriesTypeStackedBar: {
288 288 QStackedBarSeries* stackedBarSeries = static_cast<QStackedBarSeries*>(series);
289 289 appendMarkers(stackedBarSeries);
290 290 break;
291 291 }
292 292
293 293 case QSeries::SeriesTypePercentBar: {
294 294 QPercentBarSeries* percentBarSeries = static_cast<QPercentBarSeries*>(series);
295 295 appendMarkers(percentBarSeries);
296 296 break;
297 297 }
298 298
299 299 case QSeries::SeriesTypeScatter: {
300 300 QScatterSeries *scatterSeries = static_cast<QScatterSeries *>(series);
301 301 appendMarkers(scatterSeries);
302 302 break;
303 303 }
304 304
305 305 case QSeries::SeriesTypePie: {
306 306 QPieSeries *pieSeries = static_cast<QPieSeries *>(series);
307 307 appendMarkers(pieSeries);
308 308 break;
309 309 }
310 310
311 311 case QSeries::SeriesTypeSpline: {
312 312 QSplineSeries* splineSeries = static_cast<QSplineSeries*>(series);
313 313 appendMarkers(splineSeries);
314 314 break;
315 315 }
316 316 default: {
317 317 qDebug()<< "QLegend::createMarkers" << series->type() << "not implemented.";
318 318 break;
319 319 }
320 320 }
321 321 }
322 322
323 323 void QLegend::appendMarkers(QXYSeries* series)
324 324 {
325 325 LegendMarker* marker = new LegendMarker(series,this);
326 326 marker->setName(series->name());
327 327 marker->setBrush(series->brush());
328 328 connect(marker,SIGNAL(clicked(QSeries*,Qt::MouseButton)),this,SIGNAL(clicked(QSeries*,Qt::MouseButton)));
329 329 connect(marker,SIGNAL(destroyed()),this,SLOT(handleMarkerDestroyed()));
330 330 mMarkers.append(marker);
331 331 childItems().append(marker);
332 332 }
333 333
334 334 void QLegend::appendMarkers(QBarSeries *series)
335 335 {
336 336 foreach(QBarSet* s, series->barSets()) {
337 337 LegendMarker* marker = new LegendMarker(series,s,this);
338 338 marker->setName(s->name());
339 339 marker->setBrush(s->brush());
340 340 connect(marker,SIGNAL(clicked(QBarSet*,Qt::MouseButton)),this,SIGNAL(clicked(QBarSet*,Qt::MouseButton)));
341 connect(s,SIGNAL(changed()),marker,SLOT(changed()));
341 connect(s,SIGNAL(valueChanged()),marker,SLOT(changed()));
342 342 connect(marker,SIGNAL(destroyed()),this,SLOT(handleMarkerDestroyed()));
343 343 mMarkers.append(marker);
344 344 childItems().append(marker);
345 345 }
346 346 }
347 347
348 348 void QLegend::appendMarkers(QPieSeries *series)
349 349 {
350 350 foreach(QPieSlice* s, series->slices()) {
351 351 LegendMarker* marker = new LegendMarker(series,s,this);
352 352 marker->setName(s->label());
353 353 marker->setBrush(s->sliceBrush());
354 354 connect(marker,SIGNAL(clicked(QPieSlice*,Qt::MouseButton)),this,SIGNAL(clicked(QPieSlice*,Qt::MouseButton)));
355 355 connect(s,SIGNAL(changed()),marker,SLOT(changed()));
356 356 connect(s,SIGNAL(destroyed()),marker,SLOT(deleteLater()));
357 357 connect(marker,SIGNAL(destroyed()),this,SLOT(handleMarkerDestroyed()));
358 358 mMarkers.append(marker);
359 359 childItems().append(marker);
360 360 }
361 361 }
362 362
363 363 void QLegend::deleteMarkers(QSeries *series)
364 364 {
365 365 // Search all markers that belong to given series and delete them.
366 366 foreach (LegendMarker *m, mMarkers) {
367 367 if (m->series() == series) {
368 368 mMarkers.removeOne(m);
369 369 delete m;
370 370 }
371 371 }
372 372 }
373 373
374 374 void QLegend::layoutChanged()
375 375 {
376 376 // Calculate layout for markers and text
377 377 if (mMarkers.count() <= 0) {
378 378 // Nothing to do
379 379 return;
380 380 }
381 381
382 382 // Find out widest item.
383 383 qreal itemMaxWidth = 0;
384 384 qreal itemMaxHeight = 0;
385 385 foreach (LegendMarker* m, mMarkers) {
386 386 if (m->boundingRect().width() > itemMaxWidth) {
387 387 itemMaxWidth = m->boundingRect().width();
388 388 }
389 389 if (m->boundingRect().height() > itemMaxHeight) {
390 390 itemMaxHeight = m->boundingRect().height();
391 391 }
392 392 }
393 393
394 394 int maxHorizontalItems = boundingRect().width() / itemMaxWidth;
395 395 int maxVerticalItems = boundingRect().height() / itemMaxHeight;
396 396
397 397 if (mMarkers.count() > maxHorizontalItems * maxVerticalItems) {
398 398 // TODO: overlapping layout
399 qDebug() << "Warning. Not enough space to layout all legend items properly.";
399 //qDebug() << "Warning. Not enough space to layout all legend items properly.";
400 400 }
401 401
402 402 qreal margin = 5;
403 403 qreal totalWidth = 0;
404 404 qreal totalHeight = 0;
405 405 switch (mPreferredLayout)
406 406 {
407 407 case QLegend::PreferredLayoutHorizontal: {
408 408 /*
409 409 qreal xStep = mMaximumSize.width() / (mMarkers.count()+1);
410 410 if (xStep > itemMaxWidth) {
411 411 xStep = itemMaxWidth;
412 412 }
413 413 qreal yStep = mMaximumSize.height() / (mMarkers.count()+1);
414 414 if (yStep > itemMaxHeight) {
415 415 yStep = itemMaxHeight;
416 416 }*/
417 417 qreal xStep = itemMaxWidth;
418 418 qreal yStep = itemMaxHeight;
419 419 qreal x = mPos.x() + margin;
420 420 qreal y = mPos.y() + margin;
421 421 int row = 1;
422 422 int column = 0;
423 423 int maxRows = 1;
424 424 int maxColumns = 1;
425 425 foreach (LegendMarker* m, mMarkers) {
426 426 maxRows = row;
427 427 m->setPos(x,y);
428 428 x += xStep;
429 429 column++;
430 430 if (column > maxColumns) {
431 431 maxColumns = column;
432 432 }
433 433 if ((x + itemMaxWidth + margin*2) > (mPos.x() + mMaximumSize.width())) {
434 434 x = mPos.x() + margin;
435 435 y += yStep;
436 436 row++;
437 437 column = 0;
438 438 }
439 439 }
440 440 totalWidth = maxColumns * itemMaxWidth + margin * 2;
441 441 totalHeight = maxRows * itemMaxHeight + margin * 2;
442 442 break;
443 443 }
444 444 case QLegend::PreferredLayoutVertical: {
445 445 /*
446 446 qreal xStep = mMaximumSize.width() / (mMarkers.count()+1);
447 447 if (xStep > itemMaxWidth) {
448 448 xStep = itemMaxWidth;
449 449 }
450 450 qreal yStep = mMaximumSize.height() / (mMarkers.count()+1);
451 451 if (yStep > itemMaxHeight) {
452 452 yStep = itemMaxHeight;
453 453 }*/
454 454 qreal xStep = itemMaxWidth;
455 455 qreal yStep = itemMaxHeight;
456 456 qreal x = mPos.x() + margin;
457 457 qreal y = mPos.y() + margin;
458 458 int row = 0;
459 459 int column = 1;
460 460 int maxRows = 1;
461 461 int maxColumns = 1;
462 462 foreach (LegendMarker* m, mMarkers) {
463 463 maxColumns = column;
464 464 m->setPos(x,y);
465 465 y += yStep;
466 466 row++;
467 467 if (row > maxRows) {
468 468 maxRows = row;
469 469 }
470 470 if ((y + itemMaxHeight + margin*2) > (mPos.y() + mMaximumSize.height())) {
471 471 y = mPos.y() + margin;
472 472 x += xStep;
473 473 column++;
474 474 row = 0;
475 475 }
476 476 }
477 477 totalWidth = maxColumns * itemMaxWidth + margin * 2;
478 478 totalHeight = maxRows * itemMaxHeight + margin * 2;
479 479 break;
480 480 }
481 481 default: {
482 482 break;
483 483 }
484 484 }
485 485
486 486 mSize.setWidth(totalWidth);
487 487 mSize.setHeight(totalHeight);
488 488 }
489 489
490 490 #include "moc_qlegend.cpp"
491 491 QTCOMMERCIALCHART_END_NAMESPACE
General Comments 0
You need to be logged in to leave comments. Login now