##// END OF EJS Templates
fixed legend scrolling in detached mode. updated example
sauimone -
r1446:f8259d05b01f
parent child
Show More
@@ -1,224 +1,224
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 "mainwidget.h"
22 22 #include <QChart>
23 23 #include <QChartView>
24 24 #include <QPushButton>
25 25 #include <QLabel>
26 26 #include <QDebug>
27 27 #include <QBarSet>
28 28 #include <QBarSeries>
29 29 #include <QLegend>
30 30 #include <QFormLayout>
31 31
32 32 QTCOMMERCIALCHART_USE_NAMESPACE
33 33
34 34 MainWidget::MainWidget(QWidget *parent) :
35 35 QWidget(parent)
36 36 {
37 37 // Create buttons for ui
38 38 m_buttonLayout = new QGridLayout();
39 39 QPushButton *detachLegendButton = new QPushButton("detach legend");
40 40 connect(detachLegendButton, SIGNAL(clicked()), this, SLOT(detachLegend()));
41 41 m_buttonLayout->addWidget(detachLegendButton, 0, 0);
42 42 QPushButton *attachLegendButton = new QPushButton("attach legend");
43 43 connect(attachLegendButton, SIGNAL(clicked()), this, SLOT(attachLegend()));
44 44 m_buttonLayout->addWidget(attachLegendButton, 1, 0);
45 45
46 46 QPushButton *addSetButton = new QPushButton("add barset");
47 47 connect(addSetButton, SIGNAL(clicked()), this, SLOT(addBarset()));
48 48 m_buttonLayout->addWidget(addSetButton, 2, 0);
49 49 QPushButton *removeBarsetButton = new QPushButton("remove barset");
50 50 connect(removeBarsetButton, SIGNAL(clicked()), this, SLOT(removeBarset()));
51 51 m_buttonLayout->addWidget(removeBarsetButton, 3, 0);
52 52
53 53 QPushButton *leftButton = new QPushButton("Align legend left");
54 54 connect(leftButton, SIGNAL(clicked()), this, SLOT(setLegendLeft()));
55 55 m_buttonLayout->addWidget(leftButton, 4, 0);
56 56
57 57 QPushButton *rightButton = new QPushButton("Align legend right");
58 58 connect(rightButton, SIGNAL(clicked()), this, SLOT(setLegendRight()));
59 59 m_buttonLayout->addWidget(rightButton, 5, 0);
60 60
61 61 QPushButton *topButton = new QPushButton("Align legend top");
62 62 connect(topButton, SIGNAL(clicked()), this, SLOT(setLegendTop()));
63 63 m_buttonLayout->addWidget(topButton, 6, 0);
64 64
65 65 QPushButton *bottomButton = new QPushButton("Align legend bottom");
66 66 connect(bottomButton, SIGNAL(clicked()), this, SLOT(setLegendBottom()));
67 67 m_buttonLayout->addWidget(bottomButton, 7, 0);
68 68
69 69 m_legendPosX = new QDoubleSpinBox();
70 70 m_legendPosY = new QDoubleSpinBox();
71 71 m_legendWidth = new QDoubleSpinBox();
72 72 m_legendHeight = new QDoubleSpinBox();
73 73
74 74 connect(m_legendPosX, SIGNAL(valueChanged(double)), this, SLOT(updateLegendLayout()));
75 75 connect(m_legendPosY, SIGNAL(valueChanged(double)), this, SLOT(updateLegendLayout()));
76 76 connect(m_legendWidth, SIGNAL(valueChanged(double)), this, SLOT(updateLegendLayout()));
77 77 connect(m_legendHeight, SIGNAL(valueChanged(double)), this, SLOT(updateLegendLayout()));
78 78
79 79 QFormLayout* legendLayout = new QFormLayout();
80 80 legendLayout->addRow("Horizontal position", m_legendPosX);
81 81 legendLayout->addRow("Vertical position", m_legendPosY);
82 82 legendLayout->addRow("Width", m_legendWidth);
83 83 legendLayout->addRow("Height", m_legendHeight);
84 84 m_legendSettings = new QGroupBox("Detached legend");
85 85 m_legendSettings->setLayout(legendLayout);
86 86 m_buttonLayout->addWidget(m_legendSettings);
87 87 m_legendSettings->setVisible(false);
88 88
89 89 // Create chart view with the chart
90 90 //![1]
91 91 m_chart = new QChart();
92 92 m_chartView = new QChartView(m_chart, this);
93 93 //![1]
94 94
95 95 // Create layout for grid and detached legend
96 96 m_mainLayout = new QGridLayout();
97 97 m_mainLayout->addLayout(m_buttonLayout, 0, 0);
98 98 m_mainLayout->addWidget(m_chartView, 0, 1, 3, 1);
99 99 setLayout(m_mainLayout);
100 100
101 101 createSeries();
102 102 }
103 103
104 104 void MainWidget::createSeries()
105 105 {
106 106 //![3]
107 107 m_series = new QBarSeries();
108 108 addBarset();
109 109 addBarset();
110 110 addBarset();
111 111 addBarset();
112 112
113 113 m_chart->addSeries(m_series);
114 114 m_chart->setTitle("Legend detach example");
115 115
116 116 m_chart->legend()->setVisible(true);
117 117 m_chart->legend()->setAlignment(Qt::AlignBottom);
118 118 m_chart->axisY()->setNiceNumbersEnabled(true);
119 119
120 120 m_chartView->setRenderHint(QPainter::Antialiasing);
121 121 //![3]
122 122 }
123 123
124 124 void MainWidget::showLegendSpinbox()
125 125 {
126 126 m_legendSettings->setVisible(true);
127 127 QRectF chartViewRect = m_chartView->rect();
128 128 QRectF legendRect = m_chart->legend()->boundingRect();
129 129
130 130 m_legendPosX->setMinimum(0);
131 131 m_legendPosX->setMaximum(chartViewRect.width());
132 132 m_legendPosX->setValue(150);
133 133
134 134 m_legendPosY->setMinimum(0);
135 135 m_legendPosY->setMaximum(chartViewRect.height());
136 136 m_legendPosY->setValue(150);
137 137
138 138 m_legendWidth->setMinimum(0);
139 139 m_legendWidth->setMaximum(chartViewRect.width());
140 140 m_legendWidth->setValue(150);
141 141
142 142 m_legendHeight->setMinimum(0);
143 143 m_legendHeight->setMaximum(chartViewRect.height());
144 m_legendHeight->setValue(64);
144 m_legendHeight->setValue(75);
145 145 }
146 146
147 147 void MainWidget::hideLegendSpinbox()
148 148 {
149 149 m_legendSettings->setVisible(false);
150 150 }
151 151
152 152
153 153 void MainWidget::detachLegend()
154 154 {
155 155 //![4]
156 156 QLegend *legend = m_chart->legend();
157 157 legend->detachFromChart();
158 158
159 159 m_chart->legend()->setBackgroundVisible(true);
160 160 m_chart->legend()->setBrush(QBrush(QColor(128,128,128,128)));
161 161 //![4]
162 162
163 163 showLegendSpinbox();
164 164 updateLegendLayout();
165 165 update();
166 166 }
167 167
168 168
169 169 void MainWidget::attachLegend()
170 170 {
171 171 //![5]
172 172 QLegend *legend = m_chart->legend();
173 173 legend->attachToChart();
174 174 m_chart->legend()->setBackgroundVisible(false);
175 175 //![5]
176 176
177 177 hideLegendSpinbox();
178 178 update();
179 179 }
180 180
181 181 void MainWidget::addBarset()
182 182 {
183 183 QBarSet *barSet = new QBarSet(QString("set ") + QString::number(m_series->barsetCount()));
184 184 qreal delta = m_series->barsetCount() * 0.1;
185 185 *barSet << QPointF(0.0 + delta, 1 + delta) << QPointF(1.0 + delta, 2 + delta) << QPointF(2.0 + delta, 3 + delta) << QPointF(3.0 + delta, 4 + delta);
186 186 m_series->append(barSet);
187 187 }
188 188
189 189 void MainWidget::removeBarset()
190 190 {
191 191 QList<QBarSet*> sets = m_series->barSets();
192 192 if (sets.count() > 0) {
193 193 m_series->remove(sets.at(sets.count()-1));
194 194 }
195 195 }
196 196
197 197 void MainWidget::setLegendLeft()
198 198 {
199 199 m_chart->legend()->setAlignment(Qt::AlignLeft);
200 200 }
201 201
202 202 void MainWidget::setLegendRight()
203 203 {
204 204 m_chart->legend()->setAlignment(Qt::AlignRight);
205 205 }
206 206
207 207 void MainWidget::setLegendTop()
208 208 {
209 209 m_chart->legend()->setAlignment(Qt::AlignTop);
210 210 }
211 211
212 212 void MainWidget::setLegendBottom()
213 213 {
214 214 m_chart->legend()->setAlignment(Qt::AlignBottom);
215 215 }
216 216
217 217 void MainWidget::updateLegendLayout()
218 218 {
219 219 m_chart->legend()->setGeometry(m_legendPosX->value()
220 220 ,m_legendPosY->value()
221 221 ,m_legendWidth->value()
222 222 ,m_legendHeight->value());
223 223 m_chart->legend()->update();
224 224 }
@@ -1,621 +1,652
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 part of QtCommercial chart API.
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 /*!
65 65 \fn void QLegend::alignmentChanged()
66 66 Emitted when the alignment of the legend changes.
67 67 */
68 68
69 69 /*!
70 70 \fn qreal QLegend::minWidth() const
71 71 Returns minimum width of the legend
72 72 */
73 73
74 74 /*!
75 75 \fn qreal QLegend::minHeight() const
76 76 Returns minimum height of the legend
77 77 */
78 78
79 79 /*!
80 80 Constructs the legend object and sets the parent to \a parent
81 81 */
82 82
83 83 QLegend::QLegend(QChart *chart):QGraphicsWidget(chart),
84 84 d_ptr(new QLegendPrivate(chart->d_ptr->m_presenter,chart,this))
85 85 {
86 86 setZValue(ChartPresenter::LegendZValue);
87 87 setFlags(QGraphicsItem::ItemClipsChildrenToShape);
88 88 QObject::connect(chart->d_ptr->m_dataset,SIGNAL(seriesAdded(QAbstractSeries*,Domain*)),d_ptr.data(),SLOT(handleSeriesAdded(QAbstractSeries*,Domain*)));
89 89 QObject::connect(chart->d_ptr->m_dataset,SIGNAL(seriesRemoved(QAbstractSeries*)),d_ptr.data(),SLOT(handleSeriesRemoved(QAbstractSeries*)));
90 90 QObject::connect(chart->d_ptr->m_dataset,SIGNAL(seriesUpdated(QAbstractSeries*)),d_ptr.data(),SLOT(handleSeriesUpdated(QAbstractSeries*)));
91 91 }
92 92
93 93 /*!
94 94 Destroys the legend object. Legend is always owned by a QChart, so an application should never call this.
95 95 */
96 96 QLegend::~QLegend()
97 97 {
98 98 }
99 99
100 100 /*!
101 101 Paints the legend to given \a painter. Paremeters \a option and \a widget arent used.
102 102 */
103 103
104 104 void QLegend::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
105 105 {
106 106 Q_UNUSED(option)
107 107 Q_UNUSED(widget)
108 108 if(!d_ptr->m_backgroundVisible) return;
109 109
110 110 painter->setOpacity(opacity());
111 111 painter->setPen(d_ptr->m_pen);
112 112 painter->setBrush(d_ptr->m_brush);
113 113 painter->drawRect(boundingRect());
114 114 }
115 115
116 116 /*!
117 117 Bounding rect of legend.
118 118 */
119 119
120 120 QRectF QLegend::boundingRect() const
121 121 {
122 122 return d_ptr->m_rect;
123 123 }
124 124
125 125 /*!
126 126 Sets the \a brush of legend. Brush affects the background of legend.
127 127 */
128 128 void QLegend::setBrush(const QBrush &brush)
129 129 {
130 130 if (d_ptr->m_brush != brush) {
131 131 d_ptr->m_brush = brush;
132 132 update();
133 133 }
134 134 }
135 135
136 136 /*!
137 137 Returns the brush used by legend.
138 138 */
139 139 QBrush QLegend::brush() const
140 140 {
141 141 return d_ptr->m_brush;
142 142 }
143 143
144 144 /*!
145 145 Sets the \a pen of legend. Pen affects the legend borders.
146 146 */
147 147 void QLegend::setPen(const QPen &pen)
148 148 {
149 149 if (d_ptr->m_pen != pen) {
150 150 d_ptr->m_pen = pen;
151 151 update();
152 152 }
153 153 }
154 154
155 155 /*!
156 156 Returns the pen used by legend
157 157 */
158 158
159 159 QPen QLegend::pen() const
160 160 {
161 161 return d_ptr->m_pen;
162 162 }
163 163
164 164 /*!
165 165 \property QLegend::alignment
166 166 \brief The alignment of the legend.
167 167 */
168 168
169 169 /*!
170 170 Sets the \a alignment for legend. Legend paints on the defined position in chart. The following alignments are
171 171 supported: Qt::AlignTop, Qt::AlignBottom, Qt::AlignLeft, Qt::AlignRight. If you set more than one flag the result
172 172 is undefined.
173 173
174 174 \sa QLegend::Alignment
175 175 */
176 176 void QLegend::setAlignment(Qt::Alignment alignment)
177 177 {
178 178 if(d_ptr->m_alignment!=alignment) {
179 179 d_ptr->m_alignment = alignment;
180 180 d_ptr->updateLayout();
181 181 alignmentChanged();
182 182 }
183 183 }
184 184
185 185 /*!
186 186 Returns the preferred layout for legend
187 187 */
188 188 Qt::Alignment QLegend::alignment() const
189 189 {
190 190 return d_ptr->m_alignment;
191 191 }
192 192
193 193 /*!
194 194 Detaches the legend from chart. Chart won't change layout of the legend.
195 195 */
196 196 void QLegend::detachFromChart()
197 197 {
198 198 d_ptr->m_attachedToChart = false;
199 199 }
200 200
201 201 /*!
202 202 Attaches the legend to chart. Chart may change layout of the legend.
203 203 */
204 204 void QLegend::attachToChart()
205 205 {
206 206 d_ptr->attachToChart();
207 207 }
208 208
209 209 /*!
210 210 Returns true, if legend is attached to chart.
211 211 */
212 212 bool QLegend::isAttachedToChart()
213 213 {
214 214 return d_ptr->m_attachedToChart;
215 215 }
216 216
217 217 /*!
218 218 Sets the legend's scrolling offset to value defined by \a point.
219 219 */
220 220 void QLegend::setOffset(const QPointF& point)
221 221 {
222 222 d_ptr->setOffset(point.x(),point.y());
223 223 }
224 224
225 225 /*!
226 226 Returns the legend's scrolling offset.
227 227 */
228 228 QPointF QLegend::offset() const
229 229 {
230 230 return QPointF(d_ptr->m_offsetX,d_ptr->m_offsetY);
231 231 }
232 232
233 233 /*!
234 234 Sets the visibility of legend background to \a visible
235 235 */
236 236 void QLegend::setBackgroundVisible(bool visible)
237 237 {
238 238 if(d_ptr->m_backgroundVisible!=visible)
239 239 {
240 240 d_ptr->m_backgroundVisible=visible;
241 241 update();
242 242 }
243 243 }
244 244
245 245 /*!
246 246 Returns the visibility of legend background
247 247 */
248 248 bool QLegend::isBackgroundVisible() const
249 249 {
250 250 return d_ptr->m_backgroundVisible;
251 251 }
252 252
253 253 /*!
254 254 \internal \a event see QGraphicsWidget for details
255 255 */
256 256 void QLegend::resizeEvent(QGraphicsSceneResizeEvent *event)
257 257 {
258 258 const QRectF& rect = QRectF(QPoint(0,0),event->newSize());
259 259 QGraphicsWidget::resizeEvent(event);
260 260 if(d_ptr->m_rect != rect) {
261 261 d_ptr->m_rect = rect;
262 262 d_ptr->updateLayout();
263 263 }
264 264 }
265 265
266 266 /*!
267 267 \internal \a event see QGraphicsWidget for details
268 268 */
269 269 void QLegend::hideEvent(QHideEvent *event)
270 270 {
271 271 QGraphicsWidget::hideEvent(event);
272 272 setEnabled(false);
273 273 d_ptr->updateLayout();
274 274 }
275 275
276 276 /*!
277 277 \internal \a event see QGraphicsWidget for details
278 278 */
279 279 void QLegend::showEvent(QShowEvent *event)
280 280 {
281 281 QGraphicsWidget::showEvent(event);
282 282 setEnabled(true);
283 283 d_ptr->updateLayout();
284 284 }
285 285
286 286 qreal QLegend::minWidth() const
287 287 {
288 288 return d_ptr->m_minWidth;
289 289 }
290 290
291 291 qreal QLegend::minHeight() const
292 292 {
293 293 return d_ptr->m_minHeight;
294 294 }
295 295
296 296 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
297 297
298 298 QLegendPrivate::QLegendPrivate(ChartPresenter* presenter, QChart *chart, QLegend *q):
299 299 q_ptr(q),
300 300 m_presenter(presenter),
301 301 m_chart(chart),
302 302 m_markers(new QGraphicsItemGroup(q)),
303 303 m_alignment(Qt::AlignTop),
304 304 m_offsetX(0),
305 305 m_offsetY(0),
306 306 m_minWidth(0),
307 307 m_minHeight(0),
308 308 m_width(0),
309 309 m_height(0),
310 310 m_attachedToChart(true),
311 311 m_backgroundVisible(false)
312 312 {
313 313
314 314 }
315 315
316 316 QLegendPrivate::~QLegendPrivate()
317 317 {
318 318
319 319 }
320 320
321 321 void QLegendPrivate::setOffset(qreal x, qreal y)
322 322 {
323 323 bool scrollHorizontal = true;
324 324 switch(m_alignment) {
325 325 case Qt::AlignTop:
326 326 case Qt::AlignBottom: {
327 327 scrollHorizontal = true;
328 328 break;
329 329 }
330 330 case Qt::AlignLeft:
331 331 case Qt::AlignRight: {
332 332 scrollHorizontal = false;
333 333 break;
334 334 }
335 335 }
336 336
337 // If detached, the scrolling and layout logic is inverted.
337 // If detached, the scrolling direction is vertical instead of horizontal and vice versa.
338 338 if (!m_attachedToChart) {
339 339 scrollHorizontal = !scrollHorizontal;
340 340 }
341 341
342 // Limit offset between m_minOffset and m_maxOffset
342 343 if (scrollHorizontal) {
343 344 if(m_width<=m_rect.width()) return;
344 345
345 346 if (x != m_offsetX) {
346 m_offsetX = qBound(qreal(0), x, m_width - m_rect.width());
347 m_offsetX = qBound(m_minOffsetX, x, m_maxOffsetX);
347 348 m_markers->setPos(-m_offsetX,m_rect.top());
348 349 }
349 350 } else {
350 351 if(m_height<=m_rect.height()) return;
351 352
352 353 if (y != m_offsetY) {
353 m_offsetY = qBound(qreal(0), y, m_height - m_rect.height());
354 m_offsetY = qBound(m_minOffsetY, y, m_maxOffsetY);
354 355 m_markers->setPos(m_rect.left(),-m_offsetY);
355 356 }
356 357 }
357 358 }
358 359
359 360
360 361 void QLegendPrivate::updateLayout()
361 362 {
362 363 if (!m_attachedToChart) {
363 364 updateDetachedLayout();
364 365 return;
365 366 }
366 367
367 368 m_offsetX=0;
368 369 QList<QGraphicsItem *> items = m_markers->childItems();
369 370
370 371 if(items.isEmpty()) return;
371 372
372 373 m_minWidth=0;
373 374 m_minHeight=0;
374 375
375 376 switch(m_alignment) {
376 377
377 378 case Qt::AlignTop:
378 379 case Qt::AlignBottom: {
379 380 QPointF point = m_rect.topLeft();
380 381 m_width = 0;
381 382 foreach (QGraphicsItem *item, items) {
382 383 item->setPos(point.x(),m_rect.height()/2 -item->boundingRect().height()/2);
383 384 const QRectF& rect = item->boundingRect();
384 385 qreal w = rect.width();
385 386 m_minWidth=qMax(m_minWidth,w);
386 387 m_minHeight=qMax(m_minHeight,rect.height());
387 388 m_width+=w;
388 389 point.setX(point.x() + w);
389 390 }
390 391 if(m_width<m_rect.width()) {
391 392 m_markers->setPos(m_rect.width()/2-m_width/2,m_rect.top());
392 393 }
393 394 else {
394 395 m_markers->setPos(m_rect.topLeft());
395 396 }
396 397 m_height=m_minHeight;
397 398 }
398 399 break;
399 400 case Qt::AlignLeft:
400 401 case Qt::AlignRight: {
401 402 QPointF point = m_rect.topLeft();
402 403 m_height = 0;
403 404 foreach (QGraphicsItem *item, items) {
404 405 item->setPos(point);
405 406 const QRectF& rect = item->boundingRect();
406 407 qreal h = rect.height();
407 408 m_minWidth=qMax(m_minWidth,rect.width());
408 409 m_minHeight=qMax(m_minHeight,h);
409 410 m_height+=h;
410 411 point.setY(point.y() + h);
411 412 }
412 413 if(m_height<m_rect.height()) {
413 414 m_markers->setPos(m_rect.left(),m_rect.height()/2-m_height/2);
414 415 }
415 416 else {
416 417 m_markers->setPos(m_rect.topLeft());
417 418 }
418 419 m_width=m_minWidth;
419 420 }
420 421 break;
421 422 }
422 423
424 m_minOffsetX = 0;
425 m_minOffsetY = 0;
426 m_maxOffsetX = m_width - m_rect.width();
427 m_maxOffsetY = m_height - m_rect.height();
428
423 429 m_presenter->updateLayout();
424 430 }
425 431
426 432 void QLegendPrivate::updateDetachedLayout()
427 433 {
434 // Detached layout is different.
435 // In detached mode legend may have multiple rows and columns, so layout calculations
436 // differ a log from attached mode.
437 // Also the scrolling logic is bit different.
428 438 m_offsetX=0;
439 m_offsetY=0;
429 440 QList<QGraphicsItem *> items = m_markers->childItems();
430 441
431 442 if(items.isEmpty()) return;
432 443
433 444 m_minWidth = 0;
434 445 m_minHeight = 0;
435 446
436 447 switch (m_alignment) {
437 448 case Qt::AlignTop: {
438 449 QPointF point = m_rect.topLeft();
439 450 m_width = 0;
440 451 m_height = 0;
441 452 for (int i=0; i<items.count(); i++) {
442 453 QGraphicsItem *item = items.at(i);
443 454 const QRectF& rect = item->boundingRect();
444 455 qreal w = rect.width();
445 456 qreal h = rect.height();
446 457 m_minWidth = qMax(m_minWidth,w);
447 458 m_minHeight = qMax(m_minHeight,rect.height());
448 459 m_height = qMax(m_height,h);
449 460 item->setPos(point.x(),point.y());
450 461 point.setX(point.x() + w);
451 462 if (point.x() + w > m_rect.topLeft().x() + m_rect.width()) {
452 463 // Next item would go off rect.
453 464 point.setX(m_rect.topLeft().x());
454 465 point.setY(point.y() + h);
455 466 if (i+1 < items.count()) {
456 467 m_height += h;
457 468 }
458 469 }
459 470 }
460 471 m_markers->setPos(m_rect.topLeft());
461 472 m_width = m_minWidth;
473
474 m_minOffsetX = 0;
475 m_minOffsetY = 0;
476 m_maxOffsetX = m_width - m_rect.width();
477 m_maxOffsetY = m_height - m_rect.height();
462 478 }
463 479 break;
464 480 case Qt::AlignBottom: {
465 481 QPointF point = m_rect.bottomLeft();
466 482 m_width = 0;
467 483 m_height = 0;
468 484 for (int i=0; i<items.count(); i++) {
469 485 QGraphicsItem *item = items.at(i);
470 486 const QRectF& rect = item->boundingRect();
471 487 qreal w = rect.width();
472 488 qreal h = rect.height();
473 489 m_minWidth = qMax(m_minWidth,w);
474 490 m_minHeight = qMax(m_minHeight,rect.height());
475 491 m_height = qMax(m_height,h);
476 492 item->setPos(point.x(),point.y() - h);
477 493 point.setX(point.x() + w);
478 494 if (point.x() + w > m_rect.bottomLeft().x() + m_rect.width()) {
479 495 // Next item would go off rect.
480 496 point.setX(m_rect.bottomLeft().x());
481 497 point.setY(point.y() - h);
482 498 if (i+1 < items.count()) {
483 499 m_height += h;
484 500 }
485 501 }
486 502 }
487 503 m_markers->setPos(m_rect.topLeft());
488 504 m_width = m_minWidth;
505
506 m_minOffsetX = 0;
507 m_minOffsetY = qMin(m_rect.topLeft().y(), m_rect.topLeft().y() - m_height + m_rect.height());
508 m_maxOffsetX = m_width - m_rect.width();
509 m_maxOffsetY = 0;
489 510 }
490 511 break;
491 512 case Qt::AlignLeft: {
492 513 QPointF point = m_rect.topLeft();
493 514 m_width = 0;
494 515 m_height = 0;
495 516 qreal maxWidth = 0;
496 517 for (int i=0; i<items.count(); i++) {
497 518 QGraphicsItem *item = items.at(i);
498 519 const QRectF& rect = item->boundingRect();
499 520 qreal w = rect.width();
500 521 qreal h = rect.height();
501 522 m_minWidth = qMax(m_minWidth,rect.width());
502 523 m_minHeight = qMax(m_minHeight,h);
503 524 maxWidth = qMax(maxWidth,w);
504 m_width = qMax(m_width, maxWidth);
505 525 item->setPos(point.x(),point.y());
506 526 point.setY(point.y() + h);
507 527 if (point.y() + h > m_rect.topLeft().y() + m_rect.height()) {
508 528 // Next item would go off rect.
509 529 point.setX(point.x() + maxWidth);
510 530 point.setY(m_rect.topLeft().y());
511 531 if (i+1 < items.count()) {
512 532 m_width += maxWidth;
513 533 maxWidth = 0;
514 534 }
515 535 }
516 536 }
537 m_width += maxWidth;
517 538 m_markers->setPos(m_rect.topLeft());
518 539 m_height = m_minHeight;
540
541 m_minOffsetX = 0;
542 m_minOffsetY = 0;
543 m_maxOffsetX = m_width - m_rect.width();
544 m_maxOffsetY = m_height - m_rect.height();
519 545 }
520 546 break;
521 547 case Qt::AlignRight: {
522 548 QPointF point = m_rect.topRight();
523 549 m_width = 0;
524 550 m_height = 0;
525 551 qreal maxWidth = 0;
526 552 for (int i=0; i<items.count(); i++) {
527 553 QGraphicsItem *item = items.at(i);
528 554 const QRectF& rect = item->boundingRect();
529 555 qreal w = rect.width();
530 556 qreal h = rect.height();
531 557 m_minWidth = qMax(m_minWidth,rect.width());
532 558 m_minHeight = qMax(m_minHeight,h);
533 559 maxWidth = qMax(maxWidth,w);
534 m_width = qMax(m_width, maxWidth);
535 560 item->setPos(point.x() - w,point.y());
536 561 point.setY(point.y() + h);
537 562 if (point.y() + h > m_rect.topLeft().y() + m_rect.height()) {
538 563 // Next item would go off rect.
539 564 point.setX(point.x() - maxWidth);
540 565 point.setY(m_rect.topLeft().y());
541 566 if (i+1 < items.count()) {
542 567 m_width += maxWidth;
543 568 maxWidth = 0;
544 569 }
545 570 }
546 571 }
572 m_width += maxWidth;
547 573 m_markers->setPos(m_rect.topLeft());
548 574 m_height = m_minHeight;
575
576 m_minOffsetX = qMin(m_rect.topLeft().x(), m_rect.topLeft().x() - m_width + m_rect.width());
577 m_minOffsetY = 0;
578 m_maxOffsetX = 0;
579 m_maxOffsetY = m_height - m_rect.height();
549 580 }
550 581 break;
551 582 default:
552 583 break;
553 584 }
554 585 }
555 586
556 587 void QLegendPrivate::attachToChart()
557 588 {
558 589 m_attachedToChart = true;
559 590 q_ptr->setParent(m_chart);
560 591 }
561 592
562 593 void QLegendPrivate::handleSeriesAdded(QAbstractSeries *series, Domain *domain)
563 594 {
564 595 Q_UNUSED(domain)
565 596
566 597 QList<LegendMarker*> markers = series->d_ptr->createLegendMarker(q_ptr);
567 598 foreach(LegendMarker* marker, markers)
568 599 m_markers->addToGroup(marker);
569 600
570 601 if(series->type() == QAbstractSeries::SeriesTypePie) {
571 602 QPieSeries *pieSeries = static_cast<QPieSeries *>(series);
572 603 QObject::connect(pieSeries, SIGNAL(added(QList<QPieSlice*>)), this, SLOT(handleUpdatePieSeries()));
573 604 QObject::connect(pieSeries, SIGNAL(removed(QList<QPieSlice*>)), this, SLOT(handleUpdatePieSeries()));
574 605 }
575 606
576 607 updateLayout();
577 608 }
578 609
579 610 void QLegendPrivate::handleSeriesRemoved(QAbstractSeries *series)
580 611 {
581 612 QList<QGraphicsItem *> items = m_markers->childItems();
582 613
583 614 foreach (QGraphicsItem *markers, items) {
584 615 LegendMarker *marker = static_cast<LegendMarker*>(markers);
585 616 if (marker->series() == series) {
586 617 delete marker;
587 618 }
588 619 }
589 620
590 621 if(series->type() == QAbstractSeries::SeriesTypePie)
591 622 {
592 623 QPieSeries *pieSeries = static_cast<QPieSeries *>(series);
593 624 QObject::disconnect(pieSeries, SIGNAL(added(QList<QPieSlice*>)), this, SLOT(handleUpdatePieSeries()));
594 625 QObject::disconnect(pieSeries, SIGNAL(removed(QList<QPieSlice*>)), this, SLOT(handleUpdatePieSeries()));
595 626 }
596 627
597 628 updateLayout();
598 629 }
599 630
600 631 void QLegendPrivate::handleSeriesUpdated(QAbstractSeries *series)
601 632 {
602 633 // TODO: find out which markers are are added or removed. Update them
603 634 // TODO: better implementation
604 635 handleSeriesRemoved(series);
605 636 Domain domain;
606 637 handleSeriesAdded(series, &domain);
607 638 }
608 639
609 640 void QLegendPrivate::handleUpdatePieSeries()
610 641 {
611 642 //TODO: reimplement to be optimal
612 643 QPieSeries* series = qobject_cast<QPieSeries *> (sender());
613 644 Q_ASSERT(series);
614 645 handleSeriesRemoved(series);
615 646 handleSeriesAdded(series, 0);
616 647 }
617 648
618 649 #include "moc_qlegend.cpp"
619 650 #include "moc_qlegend_p.cpp"
620 651
621 652 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,83 +1,87
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 void updateLayout();
50 50 void updateDetachedLayout();
51 51 void attachToChart();
52 52
53 53 public Q_SLOTS:
54 54 void handleSeriesAdded(QAbstractSeries *series, Domain *domain);
55 55 void handleSeriesRemoved(QAbstractSeries *series);
56 56 void handleSeriesUpdated(QAbstractSeries *series);
57 57 void handleUpdatePieSeries(); //TODO remove this function
58 58
59 59 private:
60 60 QLegend *q_ptr;
61 61 ChartPresenter *m_presenter;
62 62 QChart* m_chart;
63 63 QGraphicsItemGroup* m_markers;
64 64 Qt::Alignment m_alignment;
65 65 QBrush m_brush;
66 66 QPen m_pen;
67 67 QRectF m_rect;
68 68 qreal m_offsetX;
69 69 qreal m_offsetY;
70 qreal m_minOffsetX;
71 qreal m_minOffsetY;
72 qreal m_maxOffsetX;
73 qreal m_maxOffsetY;
70 74 qreal m_minWidth;
71 75 qreal m_minHeight;
72 76 qreal m_width;
73 77 qreal m_height;
74 78 bool m_attachedToChart;
75 79 bool m_backgroundVisible;
76 80
77 81 friend class QLegend;
78 82
79 83 };
80 84
81 85 QTCOMMERCIALCHART_END_NAMESPACE
82 86
83 87 #endif
General Comments 0
You need to be logged in to leave comments. Login now