##// END OF EJS Templates
Fix attempt to wrong graphics items hadnling
Michal Klocek -
r790:68c6a254cbfa
parent child
Show More
@@ -1,26 +1,29
1 1 #include "legendscrollbutton_p.h"
2 #include "qlegend.h"
2 3 #include <QGraphicsSceneEvent>
3 4
4 5 QTCOMMERCIALCHART_BEGIN_NAMESPACE
5 6
6 LegendScrollButton::LegendScrollButton(ScrollButtonId id, QGraphicsItem *parent)
7 : QGraphicsPolygonItem(parent)
8 ,m_id(id)
7 LegendScrollButton::LegendScrollButton(ScrollButtonId id, QLegend *legend)
8 : QGraphicsPolygonItem(legend),
9 m_id(id),
10 m_ledgend(legend)
9 11 {
10 12 setAcceptedMouseButtons(Qt::LeftButton);
11 13 }
12 14
13 15 LegendScrollButton::ScrollButtonId LegendScrollButton::id()
14 16 {
15 17 return m_id;
16 18 }
17 19
18 20 void LegendScrollButton::mousePressEvent(QGraphicsSceneMouseEvent *event)
19 21 {
20 emit clicked(event);
22 Q_UNUSED(event);
23 m_ledgend->scrollButtonClicked(this);
21 24 }
22 25
23 26 #include "moc_legendscrollbutton_p.cpp"
24 27
25 28 QTCOMMERCIALCHART_END_NAMESPACE
26 29
@@ -1,38 +1,34
1 1 #ifndef LEGENDSCROLLBUTTON_P_H
2 2 #define LEGENDSCROLLBUTTON_P_H
3 3
4 4 #include <QObject>
5 5 #include <qchartglobal.h>
6 6 #include <QGraphicsPolygonItem>
7 7
8 8 QTCOMMERCIALCHART_BEGIN_NAMESPACE
9 9
10 class LegendScrollButton : public QObject, public QGraphicsPolygonItem
10 class QLegend;
11
12 class LegendScrollButton : public QGraphicsPolygonItem
11 13 {
12 Q_OBJECT
13 14 public:
14 15 enum ScrollButtonId {
15 16 ScrollButtonIdLeft,
16 17 ScrollButtonIdRight,
17 18 ScrollButtonIdUp,
18 19 ScrollButtonIdDown
19 20 };
20 21
21 explicit LegendScrollButton(ScrollButtonId id, QGraphicsItem *parent = 0);
22 explicit LegendScrollButton(ScrollButtonId id, QLegend *legend);
22 23 ScrollButtonId id();
23 24
24 25 virtual void mousePressEvent(QGraphicsSceneMouseEvent *event);
25 26
26 Q_SIGNALS:
27 void clicked(QGraphicsSceneMouseEvent* event);
28
29 public Q_SLOTS:
30
31 27 private:
32
33 28 ScrollButtonId m_id;
29 QLegend *m_ledgend;
34 30 };
35 31
36 32 QTCOMMERCIALCHART_END_NAMESPACE
37 33
38 34 #endif // LEGENDSCROLLBUTTON_P_H
@@ -1,115 +1,116
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 QCHART_H
22 22 #define QCHART_H
23 23
24 24 #include <QSeries>
25 25 #include <QGraphicsWidget>
26 26
27 27 class QGraphicsSceneResizeEvent;
28 28
29 29 QTCOMMERCIALCHART_BEGIN_NAMESPACE
30 30
31 31 class QSeries;
32 32 class QChartAxis;
33 33 class QLegend;
34 34 struct QChartPrivate;
35 35
36 36 class QTCOMMERCIALCHART_EXPORT QChart : public QGraphicsWidget
37 37 {
38 38 Q_OBJECT
39 39 public:
40 40 enum ChartTheme {
41 41 ChartThemeDefault,
42 42 ChartThemeLight,
43 43 ChartThemeBlueCerulean,
44 44 ChartThemeDark,
45 45 ChartThemeBrownSand,
46 46 ChartThemeBlueNcs,
47 47 ChartThemeHighContrast,
48 48 ChartThemeBlueIcy,
49 49 ChartThemeCount
50 50 };
51 51
52 52 enum AnimationOption {
53 53 NoAnimation = 0x0,
54 54 GridAxisAnimations = 0x1,
55 55 SeriesAnimations =0x2,
56 56 AllAnimations = 0x3
57 57 };
58 58
59 59 Q_DECLARE_FLAGS(AnimationOptions, AnimationOption)
60 60
61 61 public:
62 62 explicit QChart(QGraphicsItem *parent = 0, Qt::WindowFlags wFlags = 0);
63 63 ~QChart();
64 64
65 65 void addSeries(QSeries *series, QChartAxis *axisY = 0);
66 66 void removeSeries(QSeries *series);
67 67 void removeAllSeries();
68 68
69 69 void setTheme(QChart::ChartTheme theme);
70 70 QChart::ChartTheme theme() const;
71 71
72 72 void setTitle(const QString& title);
73 73 QString title() const;
74 74 void setTitleFont(const QFont& font);
75 75 QFont titleFont() const;
76 76 void setTitleBrush(const QBrush &brush);
77 77 QBrush titleBrush() const;
78 78 void setBackgroundBrush(const QBrush &brush);
79 79 QBrush backgroundBrush() const;
80 80 void setBackgroundPen(const QPen &pen);
81 81 QPen backgroundPen() const;
82 82
83 83 void setBackgroundVisible(bool visible);
84 84 bool isBackgroundVisible() const;
85 85
86 86 void setAnimationOptions(AnimationOptions options);
87 87 AnimationOptions animationOptions() const;
88 88
89 89 void zoomIn();
90 90 void zoomIn(const QRectF &rect);
91 91 void zoomOut();
92 92 void scrollLeft();
93 93 void scrollRight();
94 94 void scrollUp();
95 95 void scrollDown();
96 96
97 97 QChartAxis* axisX() const;
98 98 QChartAxis* axisY() const;
99 99
100 100 QLegend* legend() const;
101 101
102 102 protected:
103 103 void resizeEvent(QGraphicsSceneResizeEvent *event);
104 104
105 105 protected:
106 106 QScopedPointer<QChartPrivate> d_ptr;
107 107 friend class QChartView;
108 friend class QLegend;
108 109 Q_DISABLE_COPY(QChart)
109 110 };
110 111
111 112 QTCOMMERCIALCHART_END_NAMESPACE
112 113
113 114 Q_DECLARE_OPERATORS_FOR_FLAGS(QTCOMMERCIALCHART_NAMESPACE::QChart::AnimationOptions)
114 115
115 116 #endif
@@ -1,706 +1,693
1 #include "qchartglobal.h"
2 1 #include "qlegend.h"
2 #include "qchart_p.h"
3 3 #include "qseries.h"
4 4 #include "legendmarker_p.h"
5 5 #include "legendscrollbutton_p.h"
6 6 #include "qxyseries.h"
7 7 #include "qlineseries.h"
8 8 #include "qareaseries.h"
9 9 #include "qscatterseries.h"
10 10 #include "qsplineseries.h"
11 11 #include "qbarseries.h"
12 12 #include "qstackedbarseries.h"
13 13 #include "qpercentbarseries.h"
14 14 #include "qbarset.h"
15 15 #include "qpieseries.h"
16 16 #include "qpieslice.h"
17 17 #include "chartpresenter_p.h"
18 18 #include <QPainter>
19 19 #include <QPen>
20 20
21 21 #include <QGraphicsSceneEvent>
22 22
23 23 QTCOMMERCIALCHART_BEGIN_NAMESPACE
24 24
25 25 /*!
26 26 \class QLegend
27 27 \brief part of QtCommercial chart API.
28 28
29 29 QLegend is a graphical object, whics displays legend of the chart. Legend state is updated by QChart, when
30 30 series have been changed. By default, legend is drawn by QChart, but user can set a new parent to legend and
31 31 handle the drawing manually.
32 32 User isn't supposed to create or delete legend objects, but can reference it via QChart class.
33 33
34 34 \mainclass
35 35
36 36 \sa QChart, QSeries
37 37 */
38 38
39 39 /*!
40 40 \enum QLegend::Layout
41 41
42 42 This enum describes the possible position for legend inside chart.
43 43
44 44 \value LayoutTop
45 45 \value LayoutBottom
46 46 \value LayoutLeft
47 47 \value LayoutRight
48 48 */
49 49
50 50
51 51 /*!
52 52 \fn void QLegend::clicked(QSeries* series, Qt::MouseButton button)
53 53 \brief Notifies when series has been clicked on legend \a series \a button
54 54 */
55 55
56 56 /*!
57 57 \fn void QLegend::clicked(QBarSet* barset, Qt::MouseButton button)
58 58 \brief Notifies when barset has been clicked on legend \a barset \a button
59 59 */
60 60
61 61 /*!
62 62 \fn void QLegend::clicked(QPieSlice* slice, Qt::MouseButton button)
63 63 \brief Notifies when pie slice has been clicked on legend \a slice \a button
64 64 */
65 65
66 66 /*!
67 67 Constructs the legend object and sets the parent to \a parent
68 68 */
69 QLegend::QLegend(QGraphicsItem *parent) : QGraphicsObject(parent),
69 QLegend::QLegend(QChart *chart):QGraphicsWidget(chart->d_ptr->m_presenter->rootItem()),
70 70 m_margin(5),
71 71 m_pos(0,0),
72 72 m_minimumSize(50,20), // TODO: magic numbers
73 73 m_maximumSize(150,100),
74 74 m_size(m_minimumSize),
75 75 m_brush(Qt::darkGray), // TODO: default should come from theme
76 76 m_alignment(QLegend::LayoutTop),
77 77 mFirstMarker(0)
78 78 {
79 79 m_scrollButtonLeft = new LegendScrollButton(LegendScrollButton::ScrollButtonIdLeft, this);
80 80 m_scrollButtonRight = new LegendScrollButton(LegendScrollButton::ScrollButtonIdRight, this);
81 81 m_scrollButtonUp = new LegendScrollButton(LegendScrollButton::ScrollButtonIdUp, this);
82 82 m_scrollButtonDown = new LegendScrollButton(LegendScrollButton::ScrollButtonIdDown, this);
83
84 connect(m_scrollButtonLeft, SIGNAL(clicked(QGraphicsSceneMouseEvent*)),
85 this, SLOT(handleScrollButtonClicked(QGraphicsSceneMouseEvent*)));
86 connect(m_scrollButtonRight, SIGNAL(clicked(QGraphicsSceneMouseEvent*)),
87 this, SLOT(handleScrollButtonClicked(QGraphicsSceneMouseEvent*)));
88 connect(m_scrollButtonUp, SIGNAL(clicked(QGraphicsSceneMouseEvent*)),
89 this, SLOT(handleScrollButtonClicked(QGraphicsSceneMouseEvent*)));
90 connect(m_scrollButtonDown, SIGNAL(clicked(QGraphicsSceneMouseEvent*)),
91 this, SLOT(handleScrollButtonClicked(QGraphicsSceneMouseEvent*)));
92
93 83 setZValue(ChartPresenter::LegendZValue);
94 84 }
95 85
96 86 /*!
97 87 Paints the legend to given \a painter. Paremeters \a option and \a widget arent used.
98 88 */
99 89 void QLegend::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
100 90 {
101 91 Q_UNUSED(option)
102 92 Q_UNUSED(widget)
103 93
104 94 painter->setOpacity(opacity());
105 95 painter->setPen(m_pen);
106 96 painter->setBrush(m_brush);
107 97 // painter->drawRect(boundingRect());
108 98 }
109 99
110 100 /*!
111 101 Bounding rect of legend.
112 102 */
113 103 QRectF QLegend::boundingRect() const
114 104 {
115 105 return QRectF(m_pos,m_size);
116 106 }
117 107
118 108 /*!
119 109 Sets the \a brush of legend. Brush affects the background of legend.
120 110 */
121 111 void QLegend::setBrush(const QBrush &brush)
122 112 {
123 113 if (m_brush != brush) {
124 114 m_brush = brush;
125 115 update();
126 116 }
127 117 }
128 118
129 119 /*!
130 120 Returns the brush used by legend.
131 121 */
132 122 QBrush QLegend::brush() const
133 123 {
134 124 return m_brush;
135 125 }
136 126
137 127 /*!
138 128 Sets the \a pen of legend. Pen affects the legend borders.
139 129 */
140 130 void QLegend::setPen(const QPen &pen)
141 131 {
142 132 if (m_pen != pen) {
143 133 m_pen = pen;
144 134 update();
145 135 }
146 136 }
147 137
148 138 /*!
149 139 Returns the pen used by legend
150 140 */
151 141
152 142 QPen QLegend::pen() const
153 143 {
154 144 return m_pen;
155 145 }
156 146
157 147 /*!
158 148 Sets the \a preferred layout for legend. Legend tries to paint itself on the defined position in chart.
159 149 \sa QLegend::Layout
160 150 */
161 151 void QLegend::setAlignmnent(QLegend::Layout alignment)
162 152 {
163 153 m_alignment = alignment;
164 154 updateLayout();
165 155 }
166 156
167 157 /*!
168 158 Returns the preferred layout for legend
169 159 */
170 160 QLegend::Layout QLegend::alignment() const
171 161 {
172 162 return m_alignment;
173 163 }
174 164
175 165 /*!
176 166 Returns the maximum size of legend.
177 167 */
178 168 QSizeF QLegend::maximumSize() const
179 169 {
180 170 return m_maximumSize;
181 171 }
182 172
183 173 /*!
184 174 Sets the maximum \a size for legend. The legend can't grow bigger than this size. If there are
185 175 more series than legend can fit to this size, scroll buttons are displayed.
186 176 */
187 177 void QLegend::setMaximumSize(const QSizeF size)
188 178 {
189 179 m_maximumSize = size;
190 180 updateLayout();
191 181 }
192 182
193 183 /*!
194 184 Returns the current size of legend.
195 185 */
196 186 QSizeF QLegend::size() const
197 187 {
198 188 return m_size;
199 189 }
200 190
201 191 /*!
202 192 Sets the \a size of legend. If size is bigger than maximum size of legend, the legend is resized to the maximum size.
203 193 \sa setMmaximumSize()
204 194 */
205 195 void QLegend::setSize(const QSizeF size)
206 196 {
207 197 m_size = size;
208 198 if (m_size.width() > m_maximumSize.width()) {
209 199 m_size.setWidth(m_maximumSize.width());
210 200 }
211 201 if (m_size.height() > m_maximumSize.height()) {
212 202 m_size.setHeight(m_maximumSize.height());
213 203 }
214 204 }
215 205
216 206 /*!
217 207 Sets position of legend to \a pos
218 208 */
219 209 void QLegend::setPos(const QPointF &pos)
220 210 {
221 211 m_pos = pos;
222 212 updateLayout();
223 213 }
224 214
225 215 /*!
226 216 \internal \a series \a domain Should be called when series is added to chart.
227 217 */
228 218 void QLegend::handleSeriesAdded(QSeries *series, Domain *domain)
229 219 {
230 220 Q_UNUSED(domain)
231 221
232 222 createMarkers(series);
233 223 connectSeries(series);
234 224 updateLayout();
235 225 }
236 226
237 227 /*!
238 228 \internal \a series Should be called when series is removed from chart.
239 229 */
240 230 void QLegend::handleSeriesRemoved(QSeries *series)
241 231 {
242 232 disconnectSeries(series);
243 233
244 234 if (series->type() == QSeries::SeriesTypeArea) {
245 235 // This is special case. Area series has upper and lower series, which each have markers
246 236 QAreaSeries* s = static_cast<QAreaSeries *> (series);
247 237 deleteMarkers(s->upperSeries());
248 238 deleteMarkers(s->lowerSeries());
249 239 } else {
250 240 deleteMarkers(series);
251 241 }
252 242
253 243 updateLayout();
254 244 }
255 245
256 246 /*!
257 247 \internal \a slices Should be called when slices are added to pie chart.
258 248 */
259 249 void QLegend::handleAdded(QList<QPieSlice *> slices)
260 250 {
261 251 QPieSeries* series = static_cast<QPieSeries *> (sender());
262 252 foreach(QPieSlice* s, slices) {
263 253 LegendMarker* marker = new LegendMarker(series, s, this);
264 254 marker->setName(s->label());
265 255 marker->setBrush(s->brush());
266 256 connect(marker, SIGNAL(clicked(QPieSlice*,Qt::MouseButton)),
267 257 this, SIGNAL(clicked(QPieSlice*,Qt::MouseButton)));
268 258 connect(s, SIGNAL(changed()), marker, SLOT(changed()));
269 259 connect(s, SIGNAL(destroyed()), marker, SLOT(deleteLater()));
270 260 connect(marker, SIGNAL(destroyed()), this, SLOT(handleMarkerDestroyed()));
271 261 m_markers.append(marker);
272 262 childItems().append(marker);
273 263 }
274 264 updateLayout();
275 265 }
276 266
277 267 /*!
278 268 \internal \a slices Should be called when slices are removed from pie chart. Currently unused,
279 269 because removed slices are also deleted and we listen destroyed signal
280 270 */
281 271 void QLegend::handleRemoved(QList<QPieSlice *> slices)
282 272 {
283 273 Q_UNUSED(slices)
284 274 }
285 275
286 276
287 277 /*!
288 278 \internal Notifies legend that some marker has been removed. Sent by legend markers when destroyed
289 279 */
290 280 void QLegend::handleMarkerDestroyed()
291 281 {
292 282 LegendMarker* m = static_cast<LegendMarker *> (sender());
293 283 m_markers.removeOne(m);
294 284 updateLayout();
295 285 }
296 286
297 287 /*!
298 288 \internal \a event Handles clicked signals from scroll buttons
299 289 */
300 void QLegend::handleScrollButtonClicked(QGraphicsSceneMouseEvent *event)
290 void QLegend::scrollButtonClicked(LegendScrollButton *scrollButton)
301 291 {
302 Q_UNUSED(event); // Maybe later something happens with right click...
303
304 LegendScrollButton* scrollButton = static_cast<LegendScrollButton *> (sender());
305 Q_ASSERT(scrollButton);
292 Q_ASSERT(scrollButton);
306 293
307 294 switch (scrollButton->id()) {
308 295 case LegendScrollButton::ScrollButtonIdLeft:
309 296 case LegendScrollButton::ScrollButtonIdUp: {
310 297 // Lower limit is same in these cases
311 298 mFirstMarker--;
312 299 checkFirstMarkerBounds();
313 300 break;
314 301 }
315 302 case LegendScrollButton::ScrollButtonIdRight:
316 303 case LegendScrollButton::ScrollButtonIdDown: {
317 304 mFirstMarker++;
318 305 checkFirstMarkerBounds();
319 306 break;
320 307 }
321 308 default: {
322 309 break;
323 310 }
324 311 }
325 312 updateLayout();
326 313 }
327 314
328 315 /*!
329 316 \internal Connects the \a series to legend. Legend listens changes in series, for example pie slices added / removed.
330 317 Not all series notify about events
331 318 */
332 319 void QLegend::connectSeries(QSeries *series)
333 320 {
334 321 // Connect relevant signals from series. Currently only pie series has interesting signals
335 322 // TODO: bar chart may have
336 323 if (series->type() == QSeries::SeriesTypePie) {
337 324 QPieSeries *pieSeries = static_cast<QPieSeries *>(series);
338 325 connect(pieSeries,SIGNAL(added(QList<QPieSlice*>)),this,SLOT(handleAdded(QList<QPieSlice*>)));
339 326 }
340 327 }
341 328
342 329 /*!
343 330 \internal Disconnects \a series from legend. No more status updates from series to legend.
344 331 */
345 332 void QLegend::disconnectSeries(QSeries *series)
346 333 {
347 334 if (series->type() == QSeries::SeriesTypePie) {
348 335 QPieSeries *pieSeries = static_cast<QPieSeries *>(series);
349 336 disconnect(pieSeries, SIGNAL(added(QList<QPieSlice *>)), this, SLOT(handleAdded(QList<QPieSlice *>)));
350 337 }
351 338 }
352 339
353 340 /*!
354 341 \internal Creates new markers for \a series. Marker contains the colored rectangle and series name.
355 342 With pie chart, created markers depend on pie slices.
356 343 With bar chart, created markers depend on bar sets.
357 344 */
358 345 void QLegend::createMarkers(QSeries *series)
359 346 {
360 347 switch (series->type())
361 348 {
362 349 case QSeries::SeriesTypeLine: {
363 350 QLineSeries *lineSeries = static_cast<QLineSeries *>(series);
364 351 appendMarkers(lineSeries);
365 352 break;
366 353 }
367 354 case QSeries::SeriesTypeArea: {
368 355 QAreaSeries *areaSeries = static_cast<QAreaSeries *>(series);
369 356 appendMarkers(areaSeries->upperSeries());
370 357 if(areaSeries->lowerSeries())
371 358 appendMarkers(areaSeries->lowerSeries());
372 359 break;
373 360 }
374 361 case QSeries::SeriesTypeBar: {
375 362 QBarSeries *barSeries = static_cast<QBarSeries *>(series);
376 363 appendMarkers(barSeries);
377 364 break;
378 365 }
379 366 case QSeries::SeriesTypeStackedBar: {
380 367 QStackedBarSeries *stackedBarSeries = static_cast<QStackedBarSeries *>(series);
381 368 appendMarkers(stackedBarSeries);
382 369 break;
383 370 }
384 371 case QSeries::SeriesTypePercentBar: {
385 372 QPercentBarSeries *percentBarSeries = static_cast<QPercentBarSeries *>(series);
386 373 appendMarkers(percentBarSeries);
387 374 break;
388 375 }
389 376 case QSeries::SeriesTypeScatter: {
390 377 QScatterSeries *scatterSeries = static_cast<QScatterSeries *>(series);
391 378 appendMarkers(scatterSeries);
392 379 break;
393 380 }
394 381 case QSeries::SeriesTypePie: {
395 382 QPieSeries *pieSeries = static_cast<QPieSeries *>(series);
396 383 appendMarkers(pieSeries);
397 384 break;
398 385 }
399 386 case QSeries::SeriesTypeSpline: {
400 387 QSplineSeries *splineSeries = static_cast<QSplineSeries *>(series);
401 388 appendMarkers(splineSeries);
402 389 break;
403 390 }
404 391 default: {
405 392 qWarning()<< "QLegend::createMarkers" << series->type() << "unknown series type.";
406 393 break;
407 394 }
408 395 }
409 396 }
410 397
411 398 /*!
412 399 \internal Helper function. Appends markers from \a series to legend.
413 400 */
414 401 void QLegend::appendMarkers(QXYSeries* series)
415 402 {
416 403 LegendMarker* marker = new LegendMarker(series,this);
417 404 marker->setName(series->name());
418 405 marker->setPen(series->pen());
419 406 marker->setBrush(series->brush());
420 407 connect(marker, SIGNAL(clicked(QSeries *, Qt::MouseButton)), this, SIGNAL(clicked(QSeries *, Qt::MouseButton)));
421 408 connect(marker, SIGNAL(destroyed()), this, SLOT(handleMarkerDestroyed()));
422 409 m_markers.append(marker);
423 410 childItems().append(marker);
424 411 }
425 412
426 413 /*!
427 414 \internal Helper function. Appends markers from \a series to legend.
428 415 */
429 416 void QLegend::appendMarkers(QBarSeries *series)
430 417 {
431 418 foreach(QBarSet* set, series->barSets()) {
432 419 LegendMarker* marker = new LegendMarker(series, set, this);
433 420 marker->setName(set->name());
434 421 marker->setPen(set->pen());
435 422 marker->setBrush(set->brush());
436 423 connect(marker, SIGNAL(clicked(QBarSet *, Qt::MouseButton)),
437 424 this, SIGNAL(clicked(QBarSet *, Qt::MouseButton)));
438 425 connect(set, SIGNAL(valueChanged()), marker, SLOT(changed()));
439 426 connect(marker, SIGNAL(destroyed()), this, SLOT(handleMarkerDestroyed()));
440 427 m_markers.append(marker);
441 428 childItems().append(marker);
442 429 }
443 430 }
444 431
445 432 /*!
446 433 \internal Helper function. Appends markers from \a series to legend.
447 434 */
448 435 void QLegend::appendMarkers(QPieSeries *series)
449 436 {
450 437 foreach(QPieSlice* slice, series->slices()) {
451 438 LegendMarker* marker = new LegendMarker(series, slice, this);
452 439 marker->setName(slice->label());
453 440 marker->setPen(slice->pen());
454 441 marker->setBrush(slice->brush());
455 442 connect(marker, SIGNAL(clicked(QPieSlice *, Qt::MouseButton)),
456 443 this, SIGNAL(clicked(QPieSlice *, Qt::MouseButton)));
457 444 connect(slice, SIGNAL(changed()), marker, SLOT(changed()));
458 445 connect(slice, SIGNAL(destroyed()), marker, SLOT(deleteLater()));
459 446 connect(marker, SIGNAL(destroyed()), this, SLOT(handleMarkerDestroyed()));
460 447 m_markers.append(marker);
461 448 childItems().append(marker);
462 449 }
463 450 }
464 451
465 452 /*!
466 453 \internal Deletes all markers that are created from \a series
467 454 */
468 455 void QLegend::deleteMarkers(QSeries *series)
469 456 {
470 457 // Search all markers that belong to given series and delete them.
471 458 foreach (LegendMarker *m, m_markers) {
472 459 if (m->series() == series) {
473 460 m_markers.removeOne(m);
474 461 delete m;
475 462 }
476 463 }
477 464 }
478 465
479 466 /*!
480 467 \internal Updates layout of legend. Tries to fit as many markers as possible up to the maximum size of legend.
481 468 If items don't fit, sets the visibility of scroll buttons accordingly.
482 469 Causes legend to be resized.
483 470 */
484 471 void QLegend::updateLayout()
485 472 {
486 473 // Calculate layout for markers and text
487 474 if (m_markers.count() <= 0) {
488 475 // Nothing to do
489 476 return;
490 477 }
491 478
492 479 // Find out widest item.
493 480 QSizeF markerMaxSize = maximumMarkerSize();
494 481 checkFirstMarkerBounds();
495 482
496 483 // Use max height as scroll button size
497 484 rescaleScrollButtons(QSize(markerMaxSize.height() ,markerMaxSize.height()));
498 485
499 486 qreal totalWidth = 0;
500 487 qreal totalHeight = 0;
501 488 switch (m_alignment)
502 489 {
503 490 // Both cases organise items horizontally
504 491 case QLegend::LayoutBottom:
505 492 case QLegend::LayoutTop: {
506 493
507 494 qreal xStep = markerMaxSize.width();
508 495 qreal x = m_pos.x() + m_margin;
509 496 qreal y = m_pos.y() + m_margin;
510 497 int column = 0;
511 498 int maxColumns = 1;
512 499 qreal scrollButtonWidth = 0;
513 500
514 501 // Set correct visibility for scroll scrollbuttons
515 502 if (scrollButtonsVisible()) {
516 503 m_scrollButtonLeft->setVisible(true);
517 504 m_scrollButtonRight->setVisible(true);
518 505 // scrollbuttons visible, so add their width to total width
519 506 totalWidth += (m_scrollButtonLeft->boundingRect().width() + m_margin) * 2;
520 507 scrollButtonWidth = m_scrollButtonLeft->boundingRect().width() + m_margin;
521 508 // start position changes by scrollbutton width
522 509 x += scrollButtonWidth;
523 510 } else {
524 511 m_scrollButtonLeft->setVisible(false);
525 512 m_scrollButtonRight->setVisible(false);
526 513 }
527 514 m_scrollButtonUp->setVisible(false);
528 515 m_scrollButtonDown->setVisible(false);
529 516
530 517 for (int i=0; i < m_markers.count(); i++) {
531 518 LegendMarker *m = m_markers.at(i);
532 519 if (i < mFirstMarker) {
533 520 // Markers before first are not visible.
534 521 m->setVisible(false);
535 522 } else {
536 523 if ((x + xStep + scrollButtonWidth + m_margin) > (m_pos.x() + m_maximumSize.width())) {
537 524 // This marker would go outside legend rect.
538 525 m->setVisible(false);
539 526 } else {
540 527 // This marker is ok
541 528 m->setVisible(true);
542 529 m->setPos(x, y);
543 530 x += xStep;
544 531 column++;
545 532 }
546 533 }
547 534 maxColumns = column;
548 535 }
549 536
550 537 m_scrollButtonLeft->setPos(m_pos.x() + m_margin, y);
551 538 m_scrollButtonRight->setPos(x + m_margin, y);
552 539
553 540 totalWidth += maxColumns * markerMaxSize.width() + m_margin * 2;
554 541 totalHeight = markerMaxSize.height() + m_margin * 2;
555 542
556 543 break;
557 544 }
558 545 // Both cases organize items vertically
559 546 case QLegend::LayoutLeft:
560 547 case QLegend::LayoutRight: {
561 548 qreal yStep = markerMaxSize.height();
562 549 qreal x = m_pos.x() + m_margin;
563 550 qreal y = m_pos.y() + m_margin;
564 551 int row = 1;
565 552 int maxRows = 1;
566 553 qreal scrollButtonHeight = 0;
567 554
568 555 // Set correct visibility for scroll scrollbuttons
569 556 if (scrollButtonsVisible()) {
570 557 m_scrollButtonUp->setVisible(true);
571 558 m_scrollButtonDown->setVisible(true);
572 559 totalHeight += (m_scrollButtonUp->boundingRect().height() + m_margin) * 2; // scrollbuttons visible, so add their height to total height
573 560 scrollButtonHeight = m_scrollButtonUp->boundingRect().height();
574 561 y += scrollButtonHeight + m_margin; // start position changes by scrollbutton height
575 562 } else {
576 563 m_scrollButtonUp->setVisible(false);
577 564 m_scrollButtonDown->setVisible(false);
578 565 }
579 566 m_scrollButtonLeft->setVisible(false);
580 567 m_scrollButtonRight->setVisible(false);
581 568
582 569 for (int i=0; i < m_markers.count(); i++) {
583 570 LegendMarker* m = m_markers.at(i);
584 571 if (i < mFirstMarker) {
585 572 // Markers before first are not visible.
586 573 m->setVisible(false);
587 574 } else {
588 575 if ((y + yStep + scrollButtonHeight) > (m_pos.y() + m_maximumSize.height())) {
589 576 // This marker would go outside legend rect.
590 577 m->setVisible(false);
591 578 } else {
592 579 // This marker is ok
593 580 m->setVisible(true);
594 581 m->setPos(x, y);
595 582 y += yStep;
596 583 row++;
597 584 }
598 585 }
599 586 maxRows = row;
600 587 }
601 588
602 589 m_scrollButtonUp->setPos(m_pos.x() + m_margin, m_pos.y() + m_margin);
603 590 m_scrollButtonDown->setPos(m_pos.x() + m_margin, y + m_margin);
604 591
605 592 totalWidth += markerMaxSize.width() + m_margin * 2;
606 593 totalHeight = maxRows * markerMaxSize.height() + m_margin * 4 + scrollButtonHeight; // TODO: check this
607 594 break;
608 595 }
609 596 default: {
610 597 break;
611 598 }
612 599 }
613 600
614 601 m_size.setWidth(totalWidth);
615 602 m_size.setHeight(totalHeight);
616 603
617 604 update();
618 605 }
619 606
620 607 /*!
621 608 \internal Sets the size of scroll buttons to \a size
622 609 */
623 610 void QLegend::rescaleScrollButtons(const QSize &size)
624 611 {
625 612 QPolygonF left;
626 613 left << QPointF(size.width(), 0) << QPointF(0, size.height() / 2) << QPointF(size.width(), size.height());
627 614 QPolygonF right;
628 615 right << QPointF(0, 0) << QPointF(size.width(), size.height() / 2) << QPointF(0, size.height());
629 616 QPolygonF up;
630 617 up << QPointF(0, size.height()) << QPointF(size.width() / 2,0) << QPointF(size.width(), size.height());
631 618 QPolygonF down;
632 619 down << QPointF(0, 0) << QPointF(size.width() / 2, size.height()) << QPointF(size.width(), 0);
633 620
634 621 m_scrollButtonLeft->setPolygon(left);
635 622 m_scrollButtonRight->setPolygon(right);
636 623 m_scrollButtonUp->setPolygon(up);
637 624 m_scrollButtonDown->setPolygon(down);
638 625 }
639 626
640 627 /*!
641 628 \internal Finds out maximum size of single marker. Marker sizes depend on series names.
642 629 */
643 630 QSizeF QLegend::maximumMarkerSize()
644 631 {
645 632 QSizeF max(0,0);
646 633 foreach (LegendMarker* m, m_markers) {
647 634 if (m->boundingRect().width() > max.width())
648 635 max.setWidth(m->boundingRect().width());
649 636 if (m->boundingRect().height() > max.height())
650 637 max.setHeight(m->boundingRect().height());
651 638 }
652 639 return max;
653 640 }
654 641
655 642 /*!
656 643 \internal Checks that first marker is in acceptable bounds. Bounds range from 0 to (maximum number of markers - visible markers)
657 644 If scrollbuttons are visible, they affect the number of visible markers.
658 645 */
659 646 void QLegend::checkFirstMarkerBounds()
660 647 {
661 648 if ((m_alignment == QLegend::LayoutLeft) || (m_alignment == QLegend::LayoutRight)) {
662 649 // Bounds limited by height.
663 650 int max;
664 651 if (scrollButtonsVisible()) {
665 652 max = (m_maximumSize.height() - m_scrollButtonLeft->boundingRect().height() * 2 - m_margin * 4) / maximumMarkerSize().height();
666 653 } else {
667 654 max = m_maximumSize.height() / maximumMarkerSize().height();
668 655 }
669 656
670 657 if (mFirstMarker > m_markers.count() - max)
671 658 mFirstMarker = m_markers.count() - max;
672 659 } else {
673 660 // Bounds limited by width
674 661 int max;
675 662 if (scrollButtonsVisible()) {
676 663 max = (m_maximumSize.width() - m_scrollButtonLeft->boundingRect().width() * 2 - m_margin*4) / maximumMarkerSize().width();
677 664 } else {
678 665 max = m_maximumSize.width() / maximumMarkerSize().width();
679 666 }
680 667
681 668 if (mFirstMarker > m_markers.count() - max)
682 669 mFirstMarker = m_markers.count() - max;
683 670 }
684 671
685 672 if (mFirstMarker < 0)
686 673 mFirstMarker = 0;
687 674 }
688 675
689 676 /*!
690 677 \internal Helper function. Visibility of scroll buttons isn't quite obvious, so helper function clarifies the logic.
691 678 */
692 679 bool QLegend::scrollButtonsVisible()
693 680 {
694 681 // Just a helper to clarify, what the magic below means :)
695 682 if ((m_alignment == QLegend::LayoutTop) || (m_alignment == QLegend::LayoutBottom)) {
696 683 return (maximumMarkerSize().width() * m_markers.count() + m_margin * 2 > m_maximumSize.width());
697 684 } else if ((m_alignment == QLegend::LayoutLeft) || (m_alignment == QLegend::LayoutRight)) {
698 685 return (maximumMarkerSize().height() * m_markers.count() + m_margin * 2 > m_maximumSize.height());
699 686 }
700 687
701 688 return (maximumMarkerSize().height() * m_markers.count() + m_margin * 2 > m_maximumSize.height());
702 689 }
703 690
704 691 #include "moc_qlegend.cpp"
705 692
706 693 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,111 +1,116
1 1 #ifndef QLEGEND_H
2 2 #define QLEGEND_H
3 3
4 #include <qchartglobal.h>
5 #include <QGraphicsObject>
4 #include <QChartGlobal>
5 #include <QGraphicsWidget>
6 6 #include <QPen>
7 7 #include <QBrush>
8 8
9 9 QTCOMMERCIALCHART_BEGIN_NAMESPACE
10 10
11 11 class Domain;
12 12 class LegendMarker;
13 13 class QPieSlice;
14 14 class QXYSeries;
15 15 class QBarSet;
16 16 class QBarSeries;
17 17 class QPieSeries;
18 18 class LegendScrollButton;
19 19 class QSeries;
20 class QChart;
20 21
21 22 // TODO: This as widget
22 class QTCOMMERCIALCHART_EXPORT QLegend : public QGraphicsObject
23 class QTCOMMERCIALCHART_EXPORT QLegend : public QGraphicsWidget
23 24 {
24 25 Q_OBJECT
25 26 public:
26 27
27 28 // We only support these alignments (for now)
28 29 enum Layout {
29 30 LayoutTop = Qt::AlignTop,
30 31 LayoutBottom = Qt::AlignBottom,
31 32 LayoutLeft = Qt::AlignLeft,
32 33 LayoutRight = Qt::AlignRight
33 34 };
35 private:
36 explicit QLegend(QChart *chart);
34 37
35 explicit QLegend(QGraphicsItem *parent = 0);
36
38 public:
37 39 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
38 40 QRectF boundingRect() const;
39 41
40 42 void setBrush(const QBrush &brush);
41 43 QBrush brush() const;
42 44
43 45 void setPen(const QPen &pen);
44 46 QPen pen() const;
45 47
46 48 void setAlignmnent(QLegend::Layout alignment);
47 49 QLegend::Layout alignment() const;
48 50
49 51 QSizeF maximumSize() const;
50 52 void setMaximumSize(const QSizeF size);
51 53
52 54 QSizeF size() const;
53 55 void setSize(const QSizeF size);
54 56 void setPos(const QPointF &pos);
55 57
58 void scrollButtonClicked(LegendScrollButton *scrollButton);
59
56 60 Q_SIGNALS:
57 61 // for interactions.
58 62 void clicked(QSeries *series, Qt::MouseButton button);
59 63 void clicked(QBarSet *barset, Qt::MouseButton button);
60 64 void clicked(QPieSlice *slice, Qt::MouseButton button);
61 65
62 66 public Q_SLOTS:
63 67 // PIMPL --->
64 68 void handleSeriesAdded(QSeries *series, Domain *domain);
65 69 void handleSeriesRemoved(QSeries *series);
66 70 void handleAdded(QList<QPieSlice *> slices);
67 71 void handleRemoved(QList<QPieSlice *> slices);
68 72 void handleMarkerDestroyed();
69 void handleScrollButtonClicked(QGraphicsSceneMouseEvent *event);
73
70 74 // PIMPL <---
71 75
72 76 private:
73 77 // PIMPL --->
74 78 void connectSeries(QSeries *series);
75 79 void disconnectSeries(QSeries *series);
76 80 void createMarkers(QSeries *series);
77 81 void appendMarkers(QXYSeries *series); // All line series are derived from QXYSeries, so this works for now
78 82 void appendMarkers(QBarSeries *series);
79 83 void appendMarkers(QPieSeries *series);
80 84 void deleteMarkers(QSeries *series);
81 85 void updateLayout();
82 86 void rescaleScrollButtons(const QSize &size);
83 87 QSizeF maximumMarkerSize();
84 88 void checkFirstMarkerBounds();
85 89 bool scrollButtonsVisible();
86 90
87 91 qreal m_margin;
88 92 QPointF m_pos;
89 93 QSizeF m_minimumSize;
90 94 QSizeF m_maximumSize;
91 95 QSizeF m_size;
92 96
93 97 QList<LegendMarker *> m_markers;
94 98
95 99 QBrush m_brush;
96 100 QPen m_pen;
97 101 QLegend::Layout m_alignment;
98 102
99 103 int mFirstMarker;
100 104
101 105 LegendScrollButton *m_scrollButtonLeft;
102 106 LegendScrollButton *m_scrollButtonRight;
103 107 LegendScrollButton *m_scrollButtonUp;
104 108 LegendScrollButton *m_scrollButtonDown;
105 109
110 friend class QChart;
106 111 // <--- PIMPL
107 112 };
108 113
109 114 QTCOMMERCIALCHART_END_NAMESPACE
110 115
111 116 #endif // QLEGEND_H
General Comments 0
You need to be logged in to leave comments. Login now