##// END OF EJS Templates
Refactor qledgend handling...
Michal Klocek -
r855:e561e621da22
parent child
Show More
@@ -0,0 +1,259
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Digia Plc
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
7 ** This file is part of the Qt Commercial Charts Add-on.
8 **
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
14 **
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
18 **
19 ****************************************************************************/
20
21 #include "scroller_p.h"
22 #include "qlegend.h"
23 #include <QGraphicsSceneMouseEvent>
24
25 QTCOMMERCIALCHART_BEGIN_NAMESPACE
26
27 Scroller::Scroller(QLegend* legend):
28 m_ticker(this),
29 m_state(Idle),
30 m_moveThreshold(10),
31 m_timeTreshold(50),
32 m_legend(legend)
33 {
34
35 }
36
37 Scroller::~Scroller()
38 {
39 }
40
41 void Scroller::mousePressEvent(QGraphicsSceneMouseEvent* event)
42 {
43 if (event->button() == Qt::LeftButton) {
44
45 switch (m_state) {
46 case Idle:
47 {
48 m_state = Pressed;
49 m_offset = offset();
50 m_press = event->pos();
51 m_timeStamp = QTime::currentTime();
52 event->accept();
53 break;
54 }
55 case Scroll:
56 {
57 m_state = Stop;
58 m_speed = QPoint(0, 0);
59 m_offset = offset();
60 m_press = event->pos();
61 event->accept();
62 break;
63 }
64 case Pressed:
65 case Move:
66 case Stop:
67 qWarning() << __FUNCTION__<<"Scroller unexpected state" << m_state;
68 event->ignore();
69 break;
70 }
71 }
72 }
73
74 void Scroller::mouseMoveEvent(QGraphicsSceneMouseEvent* event)
75 {
76 QPointF delta = event->pos() - m_press;
77
78 switch (m_state) {
79 case Pressed:
80 case Stop:
81 {
82 if (qAbs(delta.x()) > m_moveThreshold || qAbs(delta.y()) > m_moveThreshold) {
83 m_state = Move;
84 m_timeStamp = QTime::currentTime();
85 m_distance = QPointF(0, 0);
86 m_press = event->pos();
87 event->accept();
88 break;
89 }
90 else {
91 event->ignore();
92 break;
93 }
94 }
95 case Move:
96 {
97 setOffset(m_offset - delta);
98 calculateSpeed(event->pos());
99 event->accept();
100 break;
101 }
102 case Idle:
103 case Scroll:
104 qWarning() << __FUNCTION__<<"Scroller unexpected state" << m_state;
105 event->ignore();
106 break;
107 }
108
109 }
110
111 void Scroller::mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
112 {
113 if (event->button() == Qt::LeftButton) {
114
115 switch (m_state) {
116
117 case Scroll:
118 m_state = Stop;
119 m_speed = QPointF(0, 0);
120 m_offset = offset();
121 event->accept();
122 break;
123 case Pressed:
124 {
125 m_state = Idle;
126 //if (m_timeStamp.elapsed() < m_clickedPressDelay) {
127
128 //emit clicked(m_offset.toPoint());
129 //}
130 event->accept();
131 break;
132 }
133 case Move:
134 {
135 calculateSpeed(event->pos());
136 m_offset = offset();
137 m_press = event->pos();
138 if (m_speed == QPointF(0, 0)) {
139 m_state = Idle;
140 }
141 else {
142 m_speed /= 4;
143 m_state = Scroll;
144 m_ticker.start(20);
145 }
146 event->accept();
147 break;
148 }
149
150 case Stop:
151 case Idle:
152 qWarning() << __FUNCTION__<<"Scroller unexpected state" << m_state;
153 event->ignore();
154 break;
155
156 }
157 }
158 }
159
160 void Scroller::scrollTick()
161 {
162 switch (m_state) {
163 case Scroll:
164 {
165 lowerSpeed(m_speed);
166 setOffset(m_offset - m_speed);
167 m_offset = offset();
168 if (m_speed == QPointF(0, 0)) {
169 m_state = Idle;
170 m_ticker.stop();
171 }
172 break;
173 }
174 case Stop:
175 m_ticker.stop();
176 break;
177 case Idle:
178 case Move:
179 case Pressed:
180 qWarning() << __FUNCTION__<<"Scroller unexpected state" << m_state;
181 m_ticker.stop();
182 break;
183
184 }
185 }
186
187 void Scroller::lowerSpeed(QPointF& speed, qreal maxSpeed)
188 {
189 qreal x = qBound(-maxSpeed, speed.x(), maxSpeed);
190 qreal y = qBound(-maxSpeed, speed.y(), maxSpeed);
191
192 x = (x == 0) ? x :
193 (x > 0) ? qMax(qreal(0), x - m_fraction.x()) : qMin(qreal(0), x + m_fraction.x());
194 y = (y == 0) ? y :
195 (y > 0) ? qMax(qreal(0), y - m_fraction.y()) : qMin(qreal(0), y + m_fraction.y());
196 speed.setX(x);
197 speed.setY(y);
198 }
199
200 void Scroller::calculateSpeed(const QPointF& position)
201 {
202 if (m_timeStamp.elapsed() > m_timeTreshold) {
203
204 QPointF distance = position - m_press;
205
206 m_timeStamp = QTime::currentTime();
207 m_speed = distance - m_distance;
208 m_distance = distance;
209
210 qreal fraction = qMax(qAbs(m_speed.x()), qAbs(m_speed.y()));
211
212 if (fraction != 0) {
213 m_fraction.setX(qAbs(m_speed.x() / fraction));
214 m_fraction.setY(qAbs(m_speed.y() / fraction));
215 }
216 else {
217 m_fraction.setX(1);
218 m_fraction.setY(1);
219 }
220 }
221 }
222
223 void Scroller::setOffset(const QPointF& point)
224 {
225 m_legend->setOffset(point);
226 }
227
228 QPointF Scroller::offset() const
229 {
230 return m_legend->offset();
231 }
232
233 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
234
235 ScrollTicker::ScrollTicker(Scroller *scroller,QObject* parent):QObject(parent),
236 m_scroller(scroller)
237 {
238
239 }
240
241 void ScrollTicker::start(int interval)
242 {
243 if (!m_timer.isActive()){
244 m_timer.start(interval, this);
245 }
246 }
247
248 void ScrollTicker::stop()
249 {
250 m_timer.stop();
251 }
252
253 void ScrollTicker::timerEvent(QTimerEvent *event)
254 {
255 Q_UNUSED(event);
256 m_scroller->scrollTick();
257 }
258
259 QTCOMMERCIALCHART_END_NAMESPACE
@@ -0,0 +1,107
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Digia Plc
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
7 ** This file is part of the Qt Commercial Charts Add-on.
8 **
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
14 **
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
18 **
19 ****************************************************************************/
20
21 // W A R N I N G
22 // -------------
23 //
24 // This file is not part of the QtCommercial Chart API. It exists purely as an
25 // implementation detail. This header file may change from version to
26 // version without notice, or even be removed.
27 //
28 // We mean it.
29
30 #ifndef SCROLLER_P_H_
31 #define SCROLLER_P_H_
32
33 #include "qchartglobal.h"
34 #include <QBasicTimer>
35 #include <QTime>
36 #include <QPointF>
37
38 class QGraphicsSceneMouseEvent;
39
40 QTCOMMERCIALCHART_BEGIN_NAMESPACE
41
42 class Scroller;
43 class QLegend;
44
45 class ScrollTicker : public QObject
46 {
47 public:
48 ScrollTicker(Scroller *scroller,QObject *parent=0);
49 void start(int interval);
50 void stop();
51 protected:
52 void timerEvent(QTimerEvent *event);
53
54 private:
55 QBasicTimer m_timer;
56 Scroller *m_scroller;
57 };
58
59 class Scroller
60 {
61 public:
62 enum State {
63 Idle,
64 Pressed,
65 Move,
66 Scroll,
67 Stop
68 };
69
70 explicit Scroller(QLegend* legend);
71 virtual ~Scroller();
72
73 virtual void setOffset(const QPointF& point);
74 virtual QPointF offset() const;
75
76 public:
77 void scrollTick();
78
79
80 public:
81 void mousePressEvent(QGraphicsSceneMouseEvent* event);
82 void mouseMoveEvent(QGraphicsSceneMouseEvent* event);
83 void mouseReleaseEvent(QGraphicsSceneMouseEvent* event);
84
85 private:
86 void calculateSpeed(const QPointF& position);
87 void lowerSpeed(QPointF& speed,qreal maxSpeed=100);
88
89 private:
90 ScrollTicker m_ticker;
91 State m_state;
92 QTime m_timeStamp;
93 QPointF m_press;
94 QPointF m_offset;
95 QPointF m_speed;
96 QPointF m_distance;
97 QPointF m_fraction;
98 int m_moveThreshold;
99 int m_timeTreshold;
100 QLegend* m_legend;
101
102
103 };
104
105 QTCOMMERCIALCHART_END_NAMESPACE
106
107 #endif /* SCROLLER_P_H_ */
@@ -60,6 +60,7 ThemeWidget::ThemeWidget(QWidget* parent) :
60 settingsLayout->addWidget(m_themeComboBox);
60 settingsLayout->addWidget(m_themeComboBox);
61 settingsLayout->addWidget(new QLabel("Animation:"));
61 settingsLayout->addWidget(new QLabel("Animation:"));
62 settingsLayout->addWidget(m_animatedComboBox);
62 settingsLayout->addWidget(m_animatedComboBox);
63 settingsLayout->addWidget(new QLabel("Legend:"));
63 settingsLayout->addWidget(m_legendComboBox);
64 settingsLayout->addWidget(m_legendComboBox);
64 settingsLayout->addWidget(m_antialiasCheckBox);
65 settingsLayout->addWidget(m_antialiasCheckBox);
65 settingsLayout->addStretch();
66 settingsLayout->addStretch();
@@ -98,6 +99,7 ThemeWidget::ThemeWidget(QWidget* parent) :
98
99
99 // Set defaults
100 // Set defaults
100 m_antialiasCheckBox->setChecked(true);
101 m_antialiasCheckBox->setChecked(true);
102 updateUI();
101 }
103 }
102
104
103 ThemeWidget::~ThemeWidget()
105 ThemeWidget::~ThemeWidget()
@@ -164,7 +166,7 QComboBox* ThemeWidget::createAnimationBox() const
164 QComboBox* ThemeWidget::createLegendBox() const
166 QComboBox* ThemeWidget::createLegendBox() const
165 {
167 {
166 QComboBox* legendComboBox = new QComboBox();
168 QComboBox* legendComboBox = new QComboBox();
167 legendComboBox->addItem("Legend None", -1);
169 legendComboBox->addItem("No Legend ", 0);
168 legendComboBox->addItem("Legend Top", QLegend::AlignmentTop);
170 legendComboBox->addItem("Legend Top", QLegend::AlignmentTop);
169 legendComboBox->addItem("Legend Bottom", QLegend::AlignmentBottom);
171 legendComboBox->addItem("Legend Bottom", QLegend::AlignmentBottom);
170 legendComboBox->addItem("Legend Left", QLegend::AlignmentLeft);
172 legendComboBox->addItem("Legend Left", QLegend::AlignmentLeft);
@@ -355,17 +357,17 void ThemeWidget::updateUI()
355 chartView->chart()->setAnimationOptions(options);
357 chartView->chart()->setAnimationOptions(options);
356 }
358 }
357
359
358 int alignment(m_legendComboBox->itemData(m_legendComboBox->currentIndex()).toInt());
360 QLegend::Alignments alignment(m_legendComboBox->itemData(m_legendComboBox->currentIndex()).toInt());
359 if (alignment == -1) {
361
362 if (!alignment) {
360 foreach (QChartView *chartView, m_charts) {
363 foreach (QChartView *chartView, m_charts) {
361 chartView->chart()->legend()->setVisible(false);
364 chartView->chart()->legend()->hide();
362 }
365 }
363 } else {
364 QLegend::Alignments legendAlignment(alignment);
365 foreach (QChartView *chartView, m_charts) {
366 chartView->chart()->legend()->setAlignmnent(legendAlignment);
367 chartView->chart()->legend()->setVisible(true);
368 }
366 }
367 else
368 foreach (QChartView *chartView, m_charts) {
369 chartView->chart()->legend()->setAlignmnent(alignment);
370 chartView->chart()->legend()->show();
369 }
371 }
370 }
372 }
371
373
@@ -58,6 +58,7 public: // from QChartSeries
58 Q_SIGNALS:
58 Q_SIGNALS:
59 void updated();
59 void updated();
60 void clicked(const QPointF &point);
60 void clicked(const QPointF &point);
61 void selected();
61
62
62 private:
63 private:
63 QBrush m_brush;
64 QBrush m_brush;
@@ -283,6 +283,9 void Axis::setLayout(QVector<qreal> &layout)
283 Q_ASSERT(labels.size() == ticksList.size());
283 Q_ASSERT(labels.size() == ticksList.size());
284 Q_ASSERT(layout.size() == ticksList.size());
284 Q_ASSERT(layout.size() == ticksList.size());
285
285
286 qreal minWidth = 0;
287 qreal minHeight = 0;
288
286 switch (m_type)
289 switch (m_type)
287 {
290 {
288 case X_AXIS:
291 case X_AXIS:
@@ -296,12 +299,18 void Axis::setLayout(QVector<qreal> &layout)
296 QGraphicsSimpleTextItem *labelItem = static_cast<QGraphicsSimpleTextItem*>(labels.at(i));
299 QGraphicsSimpleTextItem *labelItem = static_cast<QGraphicsSimpleTextItem*>(labels.at(i));
297 if (!categories || i<1) {
300 if (!categories || i<1) {
298 labelItem->setText(ticksList.at(i));
301 labelItem->setText(ticksList.at(i));
299 QPointF center = labelItem->boundingRect().center();
302 const QRectF& rect = labelItem->boundingRect();
303 minWidth+=rect.width();
304 minHeight=qMax(rect.height(),minHeight);
305 QPointF center = rect.center();
300 labelItem->setTransformOriginPoint(center.x(), center.y());
306 labelItem->setTransformOriginPoint(center.x(), center.y());
301 labelItem->setPos(layout[i] - center.x(), m_rect.bottom() + label_padding);
307 labelItem->setPos(layout[i] - center.x(), m_rect.bottom() + label_padding);
302 } else {
308 } else {
303 labelItem->setText(ticksList.at(i));
309 labelItem->setText(ticksList.at(i));
304 QPointF center = labelItem->boundingRect().center();
310 const QRectF& rect = labelItem->boundingRect();
311 minWidth+=rect.width();
312 minHeight=qMax(rect.height()+label_padding,minHeight);
313 QPointF center = rect.center();
305 labelItem->setTransformOriginPoint(center.x(), center.y());
314 labelItem->setTransformOriginPoint(center.x(), center.y());
306 labelItem->setPos(layout[i] - (layout[i] - layout[i-1])/2 - center.x(), m_rect.bottom() + label_padding);
315 labelItem->setPos(layout[i] - (layout[i] - layout[i-1])/2 - center.x(), m_rect.bottom() + label_padding);
307 }
316 }
@@ -313,6 +322,7 void Axis::setLayout(QVector<qreal> &layout)
313 lineItem = static_cast<QGraphicsLineItem*>(axis.at(i+1));
322 lineItem = static_cast<QGraphicsLineItem*>(axis.at(i+1));
314 lineItem->setLine(layout[i],m_rect.bottom(),layout[i],m_rect.bottom()+5);
323 lineItem->setLine(layout[i],m_rect.bottom(),layout[i],m_rect.bottom()+5);
315 }
324 }
325
316 }
326 }
317 break;
327 break;
318
328
@@ -328,14 +338,20 void Axis::setLayout(QVector<qreal> &layout)
328
338
329 if (!categories || i<1) {
339 if (!categories || i<1) {
330 labelItem->setText(ticksList.at(i));
340 labelItem->setText(ticksList.at(i));
331 QPointF center = labelItem->boundingRect().center();
341 const QRectF& rect = labelItem->boundingRect();
342 minWidth=qMax(rect.width()+label_padding,minWidth);
343 minHeight+=rect.height();
344 QPointF center = rect.center();
332 labelItem->setTransformOriginPoint(center.x(), center.y());
345 labelItem->setTransformOriginPoint(center.x(), center.y());
333 labelItem->setPos(m_rect.left() - labelItem->boundingRect().width() - label_padding , layout[i]-center.y());
346 labelItem->setPos(m_rect.left() - rect.width() - label_padding , layout[i]-center.y());
334 } else {
347 } else {
335 labelItem->setText(ticksList.at(i));
348 labelItem->setText(ticksList.at(i));
336 QPointF center = labelItem->boundingRect().center();
349 const QRectF& rect = labelItem->boundingRect();
350 minWidth=qMax(rect.width(),minWidth);
351 minHeight+=rect.height();
352 QPointF center = rect.center();
337 labelItem->setTransformOriginPoint(center.x(), center.y());
353 labelItem->setTransformOriginPoint(center.x(), center.y());
338 labelItem->setPos(m_rect.left() - labelItem->boundingRect().width() - label_padding , layout[i] - (layout[i] - layout[i-1])/2 -center.y());
354 labelItem->setPos(m_rect.left() - rect.width() - label_padding , layout[i] - (layout[i] - layout[i-1])/2 -center.y());
339 }
355 }
340
356
341 if ((i+1)%2 && i>1) {
357 if ((i+1)%2 && i>1) {
@@ -353,6 +369,10 void Axis::setLayout(QVector<qreal> &layout)
353 }
369 }
354
370
355 m_layoutVector=layout;
371 m_layoutVector=layout;
372
373 presenter()->setMinimumMarginWidth(this,minWidth);
374 presenter()->setMinimumMarginHeight(this,minHeight);
375
356 }
376 }
357
377
358 bool Axis::isEmpty()
378 bool Axis::isEmpty()
@@ -425,11 +445,14 void Axis::handleRangeChanged(qreal min, qreal max,int tickCount)
425
445
426 void Axis::handleGeometryChanged(const QRectF &rect)
446 void Axis::handleGeometryChanged(const QRectF &rect)
427 {
447 {
448 if(m_rect != rect)
449 {
428 m_rect = rect;
450 m_rect = rect;
429 if (isEmpty()) return;
451 if (isEmpty()) return;
430 QVector<qreal> layout = calculateLayout();
452 QVector<qreal> layout = calculateLayout();
431 updateLayout(layout);
453 updateLayout(layout);
432 }
454 }
455 }
433
456
434 void Axis::axisSelected()
457 void Axis::axisSelected()
435 {
458 {
@@ -21,6 +21,7
21 #ifndef AXISITEM_H_
21 #ifndef AXISITEM_H_
22 #define AXISITEM_H_
22 #define AXISITEM_H_
23
23
24 #include "qchartglobal.h"
24 #include "chart_p.h"
25 #include "chart_p.h"
25 #include <QGraphicsItem>
26 #include <QGraphicsItem>
26
27
@@ -100,7 +101,6 private:
100 qreal m_min;
101 qreal m_min;
101 qreal m_max;
102 qreal m_max;
102 int m_ticksCount;
103 int m_ticksCount;
103 qreal m_zoomFactor;
104
104
105 friend class AxisAnimation;
105 friend class AxisAnimation;
106 friend class AxisItem;
106 friend class AxisItem;
@@ -78,7 +78,7 public:
78
78
79 Q_SIGNALS:
79 Q_SIGNALS:
80 void clicked(QBarSet *barset, QString category, Qt::MouseButtons button); // Up to user of api, what to do with these signals
80 void clicked(QBarSet *barset, QString category, Qt::MouseButtons button); // Up to user of api, what to do with these signals
81
81 void selected();
82 //
82 //
83 void updatedBars();
83 void updatedBars();
84 void restructuredBars();
84 void restructuredBars();
@@ -19,6 +19,7
19 ****************************************************************************/
19 ****************************************************************************/
20
20
21 #include "qchart.h"
21 #include "qchart.h"
22 #include "qchart_p.h"
22 #include "qchartaxis.h"
23 #include "qchartaxis.h"
23 #include "chartpresenter_p.h"
24 #include "chartpresenter_p.h"
24 #include "chartdataset_p.h"
25 #include "chartdataset_p.h"
@@ -51,10 +52,17 ChartPresenter::ChartPresenter(QChart* chart,ChartDataSet* dataset):QObject(char
51 m_animator(0),
52 m_animator(0),
52 m_dataset(dataset),
53 m_dataset(dataset),
53 m_chartTheme(0),
54 m_chartTheme(0),
54 m_rect(QRectF(QPoint(0,0),m_chart->size())),
55 m_chartRect(QRectF(QPoint(0,0),m_chart->size())),
55 m_options(QChart::NoAnimation),
56 m_options(QChart::NoAnimation),
56 m_themeForce(false),
57 m_themeForce(false),
57 m_backgroundPadding(10)
58 m_minLeftMargin(0),
59 m_minBottomMargin(0),
60 m_backgroundItem(0),
61 m_titleItem(0),
62 m_marginBig(60),
63 m_marginSmall(20),
64 m_marginTiny(10),
65 m_chartMargins(QRect(m_marginBig,m_marginBig,0,0))
58 {
66 {
59 createConnections();
67 createConnections();
60 setTheme(QChart::ChartThemeLight, false);
68 setTheme(QChart::ChartThemeLight, false);
@@ -67,39 +75,65 ChartPresenter::~ChartPresenter()
67
75
68 void ChartPresenter::createConnections()
76 void ChartPresenter::createConnections()
69 {
77 {
70 QObject::connect(m_chart,SIGNAL(geometryChanged()),this,SLOT(handleGeometryChanged()));
71 QObject::connect(m_dataset,SIGNAL(seriesAdded(QSeries*,Domain*)),this,SLOT(handleSeriesAdded(QSeries*,Domain*)));
78 QObject::connect(m_dataset,SIGNAL(seriesAdded(QSeries*,Domain*)),this,SLOT(handleSeriesAdded(QSeries*,Domain*)));
72 QObject::connect(m_dataset,SIGNAL(seriesRemoved(QSeries*)),this,SLOT(handleSeriesRemoved(QSeries*)));
79 QObject::connect(m_dataset,SIGNAL(seriesRemoved(QSeries*)),this,SLOT(handleSeriesRemoved(QSeries*)));
73 QObject::connect(m_dataset,SIGNAL(axisAdded(QChartAxis*,Domain*)),this,SLOT(handleAxisAdded(QChartAxis*,Domain*)));
80 QObject::connect(m_dataset,SIGNAL(axisAdded(QChartAxis*,Domain*)),this,SLOT(handleAxisAdded(QChartAxis*,Domain*)));
74 QObject::connect(m_dataset,SIGNAL(axisRemoved(QChartAxis*)),this,SLOT(handleAxisRemoved(QChartAxis*)));
81 QObject::connect(m_dataset,SIGNAL(axisRemoved(QChartAxis*)),this,SLOT(handleAxisRemoved(QChartAxis*)));
75 }
82 }
76
83
77 void ChartPresenter::handleGeometryChanged()
84 void ChartPresenter::setGeometry(const QRectF& rect)
78 {
85 {
79 QRectF rect(QPoint(0,0),m_chart->size());
80 QRectF padding = m_chart->padding();
81 rect.adjust(padding.left(), padding.top(), -padding.right(), -padding.bottom());
82
83 //rewrite zoom stack
84 /*
85 for(int i=0;i<m_zoomStack.count();i++){
86 QRectF r = m_zoomStack[i];
87 qreal w = rect.width()/m_rect.width();
88 qreal h = rect.height()/m_rect.height();
89 QPointF tl = r.topLeft();
90 tl.setX(tl.x()*w);
91 tl.setY(tl.y()*h);
92 QPointF br = r.bottomRight();
93 br.setX(br.x()*w);
94 br.setY(br.y()*h);
95 r.setTopLeft(tl);
96 r.setBottomRight(br);
97 m_zoomStack[i]=r;
98 }
99 */
100 m_rect = rect;
86 m_rect = rect;
101 Q_ASSERT(m_rect.isValid());
87 Q_ASSERT(m_rect.isValid());
102 emit geometryChanged(m_rect);
88 updateLayout();
89 }
90
91 void ChartPresenter::setMinimumMarginWidth(Axis* axis, qreal width)
92 {
93 switch(axis->axisType()){
94 case Axis::X_AXIS:
95 {
96 if(width>m_chartRect.width()+ m_chartMargins.left()) {
97 m_minLeftMargin= width - m_chartRect.width();
98 updateLayout();
99 }
100 break;
101 }
102 case Axis::Y_AXIS:
103 {
104
105 if(m_minLeftMargin!=width){
106 m_minLeftMargin= width;
107 updateLayout();
108 }
109 break;
110 }
111
112 }
113 }
114
115 void ChartPresenter::setMinimumMarginHeight(Axis* axis, qreal height)
116 {
117 switch(axis->axisType()){
118 case Axis::X_AXIS:
119 {
120 if(m_minBottomMargin!=height) {
121 m_minBottomMargin= height;
122 updateLayout();
123 }
124 break;
125 }
126 case Axis::Y_AXIS:
127 {
128
129 if(height>m_chartMargins.bottom()+m_chartRect.height()){
130 m_minBottomMargin= height - m_chartRect.height();
131 updateLayout();
132 }
133 break;
134 }
135
136 }
103 }
137 }
104
138
105 void ChartPresenter::handleAxisAdded(QChartAxis* axis,Domain* domain)
139 void ChartPresenter::handleAxisAdded(QChartAxis* axis,Domain* domain)
@@ -126,7 +160,7 void ChartPresenter::handleAxisAdded(QChartAxis* axis,Domain* domain)
126
160
127 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),item,SLOT(handleGeometryChanged(const QRectF&)));
161 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),item,SLOT(handleGeometryChanged(const QRectF&)));
128 //initialize
162 //initialize
129 item->handleGeometryChanged(m_rect);
163 item->handleGeometryChanged(m_chartRect);
130 m_axisItems.insert(axis, item);
164 m_axisItems.insert(axis, item);
131 }
165 }
132
166
@@ -265,7 +299,7 void ChartPresenter::handleSeriesAdded(QSeries* series,Domain* domain)
265
299
266 //initialize
300 //initialize
267 item->handleDomainChanged(domain->minX(),domain->maxX(),domain->minY(),domain->maxY());
301 item->handleDomainChanged(domain->minX(),domain->maxX(),domain->minY(),domain->maxY());
268 if(m_rect.isValid()) item->handleGeometryChanged(m_rect);
302 if(m_chartRect.isValid()) item->handleGeometryChanged(m_chartRect);
269 m_chartItems.insert(series,item);
303 m_chartItems.insert(series,item);
270 }
304 }
271
305
@@ -334,23 +368,23 void ChartPresenter::resetAllElements()
334
368
335 void ChartPresenter::zoomIn()
369 void ChartPresenter::zoomIn()
336 {
370 {
337 QRectF rect = geometry();
371 QRectF rect = chartGeometry();
338 rect.setWidth(rect.width()/2);
372 rect.setWidth(rect.width()/2);
339 rect.setHeight(rect.height()/2);
373 rect.setHeight(rect.height()/2);
340 rect.moveCenter(geometry().center());
374 rect.moveCenter(chartGeometry().center());
341 zoomIn(rect);
375 zoomIn(rect);
342 }
376 }
343
377
344 void ChartPresenter::zoomIn(const QRectF& rect)
378 void ChartPresenter::zoomIn(const QRectF& rect)
345 {
379 {
346 QRectF r = rect.normalized();
380 QRectF r = rect.normalized();
347 r.translate(-m_chart->padding().topLeft());
381 r.translate(-m_chartMargins.topLeft());
348 if(m_animator) {
382 if(m_animator) {
349
383
350 QPointF point(r.center().x()/geometry().width(),r.center().y()/geometry().height());
384 QPointF point(r.center().x()/chartGeometry().width(),r.center().y()/chartGeometry().height());
351 m_animator->setState(ChartAnimator::ZoomInState,point);
385 m_animator->setState(ChartAnimator::ZoomInState,point);
352 }
386 }
353 m_dataset->zoomInDomain(r,geometry().size());
387 m_dataset->zoomInDomain(r,chartGeometry().size());
354 if(m_animator) {
388 if(m_animator) {
355 m_animator->setState(ChartAnimator::ShowState);
389 m_animator->setState(ChartAnimator::ShowState);
356 }
390 }
@@ -363,9 +397,9 void ChartPresenter::zoomOut()
363 m_animator->setState(ChartAnimator::ZoomOutState);
397 m_animator->setState(ChartAnimator::ZoomOutState);
364 }
398 }
365
399
366 QSizeF size = geometry().size();
400 QSizeF size = chartGeometry().size();
367 QRectF rect = geometry();
401 QRectF rect = chartGeometry();
368 rect.translate(-m_chart->padding().topLeft());
402 rect.translate(-m_chartMargins.topLeft());
369 m_dataset->zoomOutDomain(rect.adjusted(size.width()/4,size.height()/4,-size.width()/4,-size.height()/4),size);
403 m_dataset->zoomOutDomain(rect.adjusted(size.width()/4,size.height()/4,-size.width()/4,-size.height()/4),size);
370 //m_dataset->zoomOutDomain(m_zoomStack[m_zoomIndex-1],geometry().size());
404 //m_dataset->zoomOutDomain(m_zoomStack[m_zoomIndex-1],geometry().size());
371
405
@@ -383,7 +417,7 void ChartPresenter::scroll(int dx,int dy)
383 if(dy>0) m_animator->setState(ChartAnimator::ScrollDownState,QPointF());
417 if(dy>0) m_animator->setState(ChartAnimator::ScrollDownState,QPointF());
384 }
418 }
385
419
386 m_dataset->scrollDomain(dx,dy,geometry().size());
420 m_dataset->scrollDomain(dx,dy,chartGeometry().size());
387
421
388 if(m_animator){
422 if(m_animator){
389 m_animator->setState(ChartAnimator::ShowState);
423 m_animator->setState(ChartAnimator::ShowState);
@@ -395,6 +429,104 QChart::AnimationOptions ChartPresenter::animationOptions() const
395 return m_options;
429 return m_options;
396 }
430 }
397
431
432 void ChartPresenter::updateLayout()
433 {
434 if (!m_rect.isValid()) return;
435
436 // recalculate title size
437
438 QSize titleSize;
439 int titlePadding=0;
440
441 if (m_titleItem) {
442 titleSize= m_titleItem->boundingRect().size().toSize();
443 }
444
445 //defaults
446 m_chartMargins = QRect(QPoint(m_minLeftMargin>m_marginBig?m_minLeftMargin:m_marginBig,m_marginBig),QPoint(m_marginBig,m_minBottomMargin>m_marginBig?m_minBottomMargin:m_marginBig));
447 titlePadding = m_chartMargins.top()/2;
448
449 QLegend* legend = m_chart->d_ptr->m_legend;
450
451 // recalculate legend position
452 if (legend->isAttachedToChart() && legend->isEnabled()) {
453
454 QRect legendRect;
455
456 // Reserve some space for legend
457 switch (legend->alignment()) {
458
459 case QLegend::AlignmentTop: {
460 int ledgendSize = legend->minHeight();
461 int topPadding = 2*m_marginTiny + titleSize.height() + ledgendSize + m_marginTiny;
462 m_chartMargins = QRect(QPoint(m_chartMargins.left(),topPadding),QPoint(m_chartMargins.right(),m_chartMargins.bottom()));
463 m_legendMargins = QRect(QPoint(m_chartMargins.left(),topPadding - (ledgendSize + m_marginTiny)),QPoint(m_chartMargins.right(),m_rect.height()-topPadding + m_marginTiny));
464 titlePadding = m_marginTiny + m_marginTiny;
465 break;
466 }
467 case QLegend::AlignmentBottom: {
468 int ledgendSize = legend->minHeight();
469 int bottomPadding = m_marginTiny + m_marginSmall + ledgendSize + m_marginTiny + m_minBottomMargin;
470 m_chartMargins = QRect(QPoint(m_chartMargins.left(),m_chartMargins.top()),QPoint(m_chartMargins.right(),bottomPadding));
471 m_legendMargins = QRect(QPoint(m_chartMargins.left(),m_rect.height()-bottomPadding + m_marginTiny + m_minBottomMargin),QPoint(m_chartMargins.right(),m_marginTiny + m_marginSmall));
472 titlePadding = m_chartMargins.top()/2;
473 break;
474 }
475 case QLegend::AlignmentLeft: {
476 int ledgendSize = legend->minWidht();
477 int leftPadding = m_marginTiny + m_marginSmall + ledgendSize + m_marginTiny + m_minLeftMargin;
478 m_chartMargins = QRect(QPoint(leftPadding,m_chartMargins.top()),QPoint(m_chartMargins.right(),m_chartMargins.bottom()));
479 m_legendMargins = QRect(QPoint(m_marginTiny + m_marginSmall,m_chartMargins.top()),QPoint(m_rect.width()-leftPadding + m_marginTiny + m_minLeftMargin,m_chartMargins.bottom()));
480 titlePadding = m_chartMargins.top()/2;
481 break;
482 }
483 case QLegend::AlignmentRight: {
484 int ledgendSize = legend->minWidht();
485 int rightPadding = m_marginTiny + m_marginSmall + ledgendSize + m_marginTiny;
486 m_chartMargins = QRect(QPoint(m_chartMargins.left(),m_chartMargins.top()),QPoint(rightPadding,m_chartMargins.bottom()));
487 m_legendMargins = QRect(QPoint(m_rect.width()- rightPadding+ m_marginTiny ,m_chartMargins.top()),QPoint(m_marginTiny + m_marginSmall,m_chartMargins.bottom()));
488 titlePadding = m_chartMargins.top()/2;
489 break;
490 }
491 default: {
492 break;
493 }
494 }
495 }
496
497 // recalculate title position
498 if (m_titleItem) {
499 QPointF center = m_rect.center() -m_titleItem->boundingRect().center();
500 m_titleItem->setPos(center.x(),titlePadding);
501 }
502
503 //recalculate background gradient
504 if (m_backgroundItem) {
505 m_backgroundItem->setRect(m_rect.adjusted(m_marginTiny,m_marginTiny, -m_marginTiny, -m_marginTiny));
506 }
507
508 m_chartRect = m_rect.adjusted(m_chartMargins.left(),m_chartMargins.top(),-m_chartMargins.right(),-m_chartMargins.bottom());
509
510 emit geometryChanged(m_chartRect);
511 legend->setGeometry(m_rect.adjusted(m_legendMargins.left(),m_legendMargins.top(),-m_legendMargins.right(),-m_legendMargins.bottom()));
512 }
513
514 void ChartPresenter::createChartBackgroundItem()
515 {
516 if (!m_backgroundItem) {
517 m_backgroundItem = new ChartBackground(rootItem());
518 m_backgroundItem->setPen(Qt::NoPen);
519 m_backgroundItem->setZValue(ChartPresenter::BackgroundZValue);
520 }
521 }
522
523 void ChartPresenter::createChartTitleItem()
524 {
525 if (!m_titleItem) {
526 m_titleItem = new QGraphicsSimpleTextItem(rootItem());
527 m_titleItem->setZValue(ChartPresenter::BackgroundZValue);
528 }
529 }
398
530
399 #include "moc_chartpresenter_p.cpp"
531 #include "moc_chartpresenter_p.cpp"
400
532
@@ -22,6 +22,7
22 #define CHARTPRESENTER_H_
22 #define CHARTPRESENTER_H_
23
23
24 #include "qchartglobal.h"
24 #include "qchartglobal.h"
25 #include "chartbackground_p.h" //TODO fix me
25 #include "qchart.h" //becouse of QChart::ChartThemeId //TODO
26 #include "qchart.h" //becouse of QChart::ChartThemeId //TODO
26 #include "qchartaxis.h"
27 #include "qchartaxis.h"
27 #include <QRectF>
28 #include <QRectF>
@@ -55,8 +56,6 public:
55 ChartPresenter(QChart* chart,ChartDataSet *dataset);
56 ChartPresenter(QChart* chart,ChartDataSet *dataset);
56 virtual ~ChartPresenter();
57 virtual ~ChartPresenter();
57
58
58 int backgroundPadding() const { return m_backgroundPadding; }
59 QRectF geometry() const { return m_rect; }
60 ChartAnimator* animator() const { return m_animator; }
59 ChartAnimator* animator() const { return m_animator; }
61 ChartTheme *chartTheme() const { return m_chartTheme; }
60 ChartTheme *chartTheme() const { return m_chartTheme; }
62 ChartDataSet *dataSet() const { return m_dataset; }
61 ChartDataSet *dataSet() const { return m_dataset; }
@@ -73,20 +72,32 public:
73 void zoomOut();
72 void zoomOut();
74 void scroll(int dx,int dy);
73 void scroll(int dx,int dy);
75
74
76 private:
75 void setGeometry(const QRectF& rect);
76 QRectF chartGeometry() const { return m_chartRect; }
77
78 void setMinimumMarginHeight(Axis* axis, qreal height);
79 void setMinimumMarginWidth(Axis* axis, qreal width);
80 qreal minimumLeftMargin() const { return m_minLeftMargin; }
81 qreal minimumBottomMargin() const { return m_minBottomMargin; }
82
83 public: //TODO: fix me
77 void createConnections();
84 void createConnections();
78 void resetAllElements();
85 void resetAllElements();
86 void createChartBackgroundItem();
87 void createChartTitleItem();
88 QRect margins() const { return m_chartMargins;}
79
89
80 public Q_SLOTS:
90 public Q_SLOTS:
81 void handleSeriesAdded(QSeries* series,Domain* domain);
91 void handleSeriesAdded(QSeries* series,Domain* domain);
82 void handleSeriesRemoved(QSeries* series);
92 void handleSeriesRemoved(QSeries* series);
83 void handleAxisAdded(QChartAxis* axis,Domain* domain);
93 void handleAxisAdded(QChartAxis* axis,Domain* domain);
84 void handleAxisRemoved(QChartAxis* axis);
94 void handleAxisRemoved(QChartAxis* axis);
85 void handleGeometryChanged();
95 void updateLayout();
86
96
87 Q_SIGNALS:
97 Q_SIGNALS:
88 void geometryChanged(const QRectF& rect);
98 void geometryChanged(const QRectF& rect);
89
99
100
90 private:
101 private:
91 QChart* m_chart;
102 QChart* m_chart;
92 ChartAnimator* m_animator;
103 ChartAnimator* m_animator;
@@ -95,9 +106,19 private:
95 QMap<QSeries*,Chart*> m_chartItems;
106 QMap<QSeries*,Chart*> m_chartItems;
96 QMap<QChartAxis*,Axis*> m_axisItems;
107 QMap<QChartAxis*,Axis*> m_axisItems;
97 QRectF m_rect;
108 QRectF m_rect;
109 QRectF m_chartRect;
98 QChart::AnimationOptions m_options;
110 QChart::AnimationOptions m_options;
99 bool m_themeForce;
111 bool m_themeForce;
100 int m_backgroundPadding;
112 qreal m_minLeftMargin;
113 qreal m_minBottomMargin;
114 public: //TODO: fixme
115 ChartBackground* m_backgroundItem;
116 QGraphicsSimpleTextItem* m_titleItem;
117 int m_marginBig;
118 int m_marginSmall;
119 int m_marginTiny;
120 QRect m_chartMargins;
121 QRect m_legendMargins;
101
122
102 };
123 };
103
124
@@ -176,7 +176,6 void ChartTheme::decorate(QBarSeries* series, int index, bool force)
176 takeAtPos += step;
176 takeAtPos += step;
177 takeAtPos -= (int) takeAtPos;
177 takeAtPos -= (int) takeAtPos;
178 }
178 }
179 qDebug() << "pos:" << takeAtPos;
180 if (brush == sets.at(i)->brush() || force )
179 if (brush == sets.at(i)->brush() || force )
181 sets.at(i)->setBrush(colorAt(m_seriesGradients.at(colorIndex), takeAtPos));
180 sets.at(i)->setBrush(colorAt(m_seriesGradients.at(colorIndex), takeAtPos));
182
181
@@ -18,8 +18,10
18 **
18 **
19 ****************************************************************************/
19 ****************************************************************************/
20
20
21 #include "qchartglobal.h"
22 #include "legendmarker_p.h"
21 #include "legendmarker_p.h"
22 #include "qlegend.h"
23 #include "qbarseries.h"
24 #include "qpieseries.h"
23 #include <qpieslice.h>
25 #include <qpieslice.h>
24 #include <qbarset.h>
26 #include <qbarset.h>
25 #include <qxyseries.h>
27 #include <qxyseries.h>
@@ -30,95 +32,61
30
32
31 QTCOMMERCIALCHART_BEGIN_NAMESPACE
33 QTCOMMERCIALCHART_BEGIN_NAMESPACE
32
34
33 LegendMarker::LegendMarker(QSeries *series, QGraphicsItem *parent) : QGraphicsObject(parent),
35 LegendMarker::LegendMarker(QSeries* series,QLegend *legend) : QGraphicsObject(legend),
34 m_pos(0,0),
35 m_size(0,0),
36 m_boundingRect(0,0,0,0),
37 m_markerBoundingRect(0,0,0,0),
38 m_series(series),
39 m_barset(0),
40 m_pieslice(0),
41 m_textItem(new QGraphicsSimpleTextItem(this))
42 {
43 setAcceptedMouseButtons(Qt::LeftButton|Qt::RightButton);
44 }
45
46 LegendMarker::LegendMarker(QSeries *series, QBarSet *barset, QGraphicsItem *parent) : QGraphicsObject(parent),
47 m_pos(0,0),
48 m_size(0,0),
49 m_boundingRect(0,0,0,0),
50 m_markerBoundingRect(0,0,0,0),
51 m_series(series),
36 m_series(series),
52 m_barset(barset),
37 m_markerRect(0,0,10.0,10.0),
53 m_pieslice(0),
54 m_textItem(new QGraphicsSimpleTextItem(this))
55 {
56 setAcceptedMouseButtons(Qt::LeftButton|Qt::RightButton);
57 }
58
59 LegendMarker::LegendMarker(QSeries *series, QPieSlice *pieslice, QGraphicsItem *parent) : QGraphicsObject(parent),
60 m_pos(0,0),
61 m_size(0,0),
62 m_boundingRect(0,0,0,0),
38 m_boundingRect(0,0,0,0),
63 m_markerBoundingRect(0,0,0,0),
39 m_legend(legend),
64 m_series(series),
40 m_textItem(new QGraphicsSimpleTextItem(this)),
65 m_barset(0),
41 m_rectItem(new QGraphicsRectItem(this))
66 m_pieslice(pieslice),
67 m_textItem(new QGraphicsSimpleTextItem(this))
68 {
42 {
69 setAcceptedMouseButtons(Qt::LeftButton|Qt::RightButton);
43 //setAcceptedMouseButtons(Qt::LeftButton|Qt::RightButton);
70 }
44 m_rectItem->setRect(m_markerRect);
71
45 updateLayout();
72 void LegendMarker::setPos(qreal x, qreal y)
73 {
74 m_pos = QPointF(x,y);
75 layoutChanged();
76 }
46 }
77
47
78 void LegendMarker::setPen(const QPen &pen)
48 void LegendMarker::setPen(const QPen &pen)
79 {
49 {
80 m_pen = pen;
50 m_textItem->setPen(pen);
51 updateLayout();
81 }
52 }
82
53
83 QPen LegendMarker::pen() const
54 QPen LegendMarker::pen() const
84 {
55 {
85 return m_pen;
56 return m_textItem->pen();
86 }
57 }
87
58
88 void LegendMarker::setBrush(const QBrush &brush)
59 void LegendMarker::setBrush(const QBrush &brush)
89 {
60 {
90 m_brush = brush;
61 m_rectItem->setBrush(brush);
91 }
62 }
92
63
93 QBrush LegendMarker::brush() const
64 QBrush LegendMarker::brush() const
94 {
65 {
95 return m_brush;
66 return m_rectItem->brush();
96 }
67 }
97
68
98 void LegendMarker::setName(const QString name)
69 void LegendMarker::setLabel(const QString name)
99 {
70 {
100 m_textItem->setText(name);
71 m_textItem->setText(name);
101 layoutChanged();
72 updateLayout();
102 }
73 }
103
74
104 QString LegendMarker::name() const
75 void LegendMarker::setSize(const QSize& size)
105 {
76 {
106 return m_textItem->text();
77 m_markerRect = QRectF(0,0,size.width(),size.height());
107 }
78 }
108
79
109 QSeries* LegendMarker::series() const
80 QString LegendMarker::label() const
110 {
81 {
111 return m_series;
82 return m_textItem->text();
112 }
83 }
113
84
114 void LegendMarker::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
85 void LegendMarker::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
115 {
86 {
116 Q_UNUSED(option)
87 Q_UNUSED(option)
117 Q_UNUSED(widget)
88 Q_UNUSED(widget)
118
89 Q_UNUSED(painter)
119 painter->setPen(m_pen);
120 painter->setBrush(m_brush);
121 painter->drawRect(m_markerBoundingRect);
122 }
90 }
123
91
124 QRectF LegendMarker::boundingRect() const
92 QRectF LegendMarker::boundingRect() const
@@ -126,86 +94,96 QRectF LegendMarker::boundingRect() const
126 return m_boundingRect;
94 return m_boundingRect;
127 }
95 }
128
96
129 void LegendMarker::layoutChanged()
97 void LegendMarker::updateLayout()
130 {
98 {
131 QSizeF markerSize(10,10);
132 qreal margin = 2;
133
134 m_size.setHeight(markerSize.height() + 2 * margin);
135 m_size.setWidth(m_textItem->boundingRect().width() + markerSize.width() + 3 * margin);
136
99
137 m_boundingRect = QRectF(m_pos.x(),m_pos.y(),m_size.width(),m_size.height());
100 static const qreal margin = 2;
101 static const qreal space = 4;
138
102
139 m_markerBoundingRect = QRectF(m_pos.x() + margin, m_pos.y() + margin, markerSize.width(),markerSize.height());
103 const QRectF& textRect = m_textItem->boundingRect();
104 prepareGeometryChange();
105 m_boundingRect = QRectF(0,0,m_markerRect.width() + 2*margin + space + textRect.width(),qMax(m_markerRect.height()+2*margin,textRect.height()+2*margin));
106 m_textItem->setPos(m_markerRect.width() + space + margin,m_boundingRect.height()/2 - textRect.height()/2);
107 m_rectItem->setPos(margin,m_boundingRect.height()/2 - m_markerRect.height()/2);
140
108
141 m_textItem->setPos(m_pos.x() + markerSize.width() + 2 * margin, m_pos.y() + margin);
142 }
109 }
143
110
144 void LegendMarker::mousePressEvent(QGraphicsSceneMouseEvent *event)
111 void LegendMarker::mousePressEvent(QGraphicsSceneMouseEvent *event)
145 {
112 {
146 switch (m_series->type()) {
113 QGraphicsObject::mousePressEvent(event);
147 case QSeries::SeriesTypeLine:
114 emit selected();
148 case QSeries::SeriesTypeArea:
149 case QSeries::SeriesTypeScatter:
150 case QSeries::SeriesTypeSpline: {
151 emit clicked(m_series,event->button());
152 break;
153 }
154 case QSeries::SeriesTypeBar:
155 case QSeries::SeriesTypeStackedBar:
156 case QSeries::SeriesTypePercentBar: {
157 emit clicked(m_barset,event->button());
158 break;
159 }
160 case QSeries::SeriesTypePie: {
161 emit clicked(m_pieslice,event->button());
162 break;
163 }
164 default: {
165 break;
166 }
167 }
168 }
115 }
169
116
170 void LegendMarker::changed()
117 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
118
119 AreaLegendMarker::AreaLegendMarker(QAreaSeries *series,QLegend *legend) : LegendMarker(series,legend),
120 m_series(series)
171 {
121 {
172 setPen(Qt::NoPen);
122 QObject::connect(this, SIGNAL(selected()), series, SIGNAL(selected()));
173 switch (m_series->type()) {
123 QObject::connect(series,SIGNAL(updated()), this, SLOT(updated()));
174 case QSeries::SeriesTypeArea: {
124 updated();
175 QAreaSeries* s = static_cast<QAreaSeries*> (m_series);
176 setBrush(s->brush());
177 setName(s->name());
178 break;
179 }
125 }
180 case QSeries::SeriesTypeLine:
126
181 case QSeries::SeriesTypeSpline: {
127 void AreaLegendMarker::updated()
182 QXYSeries* s = static_cast<QXYSeries*> (m_series);
128 {
183 setBrush(QBrush(s->pen().color(),Qt::SolidPattern));
129 setBrush(m_series->brush());
184 setName(s->name());
130 setLabel(m_series->name());
185 break;
186 }
131 }
187 case QSeries::SeriesTypeScatter: {
132
188 QXYSeries* s = static_cast<QXYSeries*> (m_series);
133 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
189 setBrush(s->brush());
134
190 setName(s->name());
135 BarLegendMarker::BarLegendMarker(QBarSeries *series,QBarSet *barset, QLegend *legend) : LegendMarker(series,legend),
191 break;
136 m_barset(barset)
137 {
138 QObject::connect(this, SIGNAL(selected()),series, SIGNAL(selected()));
139 QObject::connect(barset, SIGNAL(valueChanged()), this, SLOT(updated()));
140 updated();
192 }
141 }
193 case QSeries::SeriesTypeBar:
142
194 case QSeries::SeriesTypeStackedBar:
143 void BarLegendMarker::updated()
195 case QSeries::SeriesTypePercentBar: {
144 {
196 setBrush(m_barset->brush());
145 setBrush(m_barset->brush());
197 setName(m_barset->name());
146 setLabel(m_barset->name());
198 break;
147 }
148
149 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
150
151 PieLegendMarker::PieLegendMarker(QPieSeries* series,QPieSlice *pieslice, QLegend *legend) : LegendMarker(series,legend),
152 m_pieslice(pieslice)
153 {
154 QObject::connect(this, SIGNAL(selected()),pieslice, SIGNAL(selected()));
155 QObject::connect(pieslice, SIGNAL(changed()), this, SLOT(updated()));
156 QObject::connect(pieslice, SIGNAL(destroyed()), this, SLOT(deleteLater())); //TODO:checkthis
157 updated();
199 }
158 }
200 case QSeries::SeriesTypePie: {
159
160 void PieLegendMarker::updated()
161 {
201 setBrush(m_pieslice->brush());
162 setBrush(m_pieslice->brush());
202 setName(m_pieslice->label());
163 setLabel(m_pieslice->label());
203 break;
164 }
165
166 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
167
168 XYLegendMarker::XYLegendMarker(QXYSeries *series, QLegend *legend) : LegendMarker(series,legend),
169 m_series(series)
170 {
171 QObject::connect(this, SIGNAL(selected()), series, SIGNAL(selected()));
172 QObject::connect(series,SIGNAL(updated()), this, SLOT(updated()));
173 updated();
204 }
174 }
205 default: {
175
206 setBrush(Qt::NoBrush);
176 void XYLegendMarker::updated()
207 break;
177 {
178 setLabel(m_series->name());
179
180 if(m_series->type()== QSeries::SeriesTypeScatter)
181 {
182 setBrush(m_series->brush());
183
208 }
184 }
185 else {
186 setBrush(QBrush(m_series->pen().color()));
209 }
187 }
210 }
188 }
211
189
@@ -30,64 +30,98
30 QTCOMMERCIALCHART_BEGIN_NAMESPACE
30 QTCOMMERCIALCHART_BEGIN_NAMESPACE
31
31
32 class QSeries;
32 class QSeries;
33 class QAreaSeries;
34 class QXYSeries;
33 class QBarSet;
35 class QBarSet;
36 class QBarSeries;
34 class QPieSlice;
37 class QPieSlice;
38 class QLegend;
39 class QPieSeries;
35
40
36 // TODO: split this to 3 different markers for series, barset and pieslice. Current implementation is easier to misuse...
37 class LegendMarker : public QGraphicsObject
41 class LegendMarker : public QGraphicsObject
38 {
42 {
39 Q_OBJECT
43 Q_OBJECT
40
44
41 public:
45 public:
42 LegendMarker(QSeries *series, QGraphicsItem *parent = 0);
46 explicit LegendMarker(QSeries* m_series,QLegend *parent);
43 LegendMarker(QSeries *series, QBarSet *barset, QGraphicsItem *parent = 0);
44 LegendMarker(QSeries *series, QPieSlice *pieslice, QGraphicsItem *parent = 0);
45
46 void setPos(qreal x, qreal y);
47
47
48 void setPen(const QPen &pen);
48 void setPen(const QPen &pen);
49 QPen pen() const;
49 QPen pen() const;
50
51 void setBrush(const QBrush &brush);
50 void setBrush(const QBrush &brush);
52 QBrush brush() const;
51 QBrush brush() const;
53
52
54 void setName(const QString name);
53 void setSize(const QSize& size);
55 QString name() const;
56
54
57 QSeries* series() const;
55 void setLabel(const QString label);
56 QString label() const;
57
58 QSeries* series() const { return m_series;}
58
59
59 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
60 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
60
61
61 QRectF boundingRect() const;
62 QRectF boundingRect() const;
62
63
63 void layoutChanged();
64 void updateLayout();
64
65
65 public:
66 protected:
66 // From QGraphicsObject
67 // From QGraphicsObject
67 void mousePressEvent(QGraphicsSceneMouseEvent *event);
68 void mousePressEvent(QGraphicsSceneMouseEvent *event);
68
69
69 Q_SIGNALS:
70 Q_SIGNALS:
70 void clicked(QSeries *series, Qt::MouseButton button);
71 void selected();
71 void clicked(QBarSet *barset, Qt::MouseButton button);
72 void clicked(QPieSlice *pieslice, Qt::MouseButton button);
73
72
74 public Q_SLOTS:
73 public Q_SLOTS:
75 void changed();
74 virtual void updated() = 0;
76
75
77 private:
76 protected:
78 QPointF m_pos;
77 QSeries* m_series;
79 QSize m_size;
78 QRectF m_markerRect;
80 QRectF m_boundingRect;
79 QRectF m_boundingRect;
81 QRectF m_markerBoundingRect;
80 QLegend* m_legend;
82 QBrush m_brush;
81 QGraphicsSimpleTextItem *m_textItem;
83 QPen m_pen;
82 QGraphicsRectItem *m_rectItem;
84
83
85 QSeries *m_series;
84 };
85
86 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
87 class XYLegendMarker : public LegendMarker
88 {
89 public:
90 XYLegendMarker(QXYSeries *series, QLegend *legend);
91 protected:
92 void updated();
93 private:
94 QXYSeries *m_series;
95 };
96 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
97 class AreaLegendMarker : public LegendMarker
98 {
99 public:
100 AreaLegendMarker(QAreaSeries *series, QLegend *legend);
101 protected:
102 void updated();
103 private:
104 QAreaSeries *m_series;
105 };
106 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
107 class BarLegendMarker : public LegendMarker
108 {
109 public:
110 BarLegendMarker(QBarSeries *barseires, QBarSet *barset,QLegend *legend);
111 protected:
112 void updated();
113 private:
86 QBarSet *m_barset;
114 QBarSet *m_barset;
115 };
116 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
117 class PieLegendMarker : public LegendMarker
118 {
119 public:
120 PieLegendMarker(QPieSeries *pieSeries, QPieSlice *pieslice, QLegend *legend);
121 protected:
122 void updated();
123 private:
87 QPieSlice *m_pieslice;
124 QPieSlice *m_pieslice;
88
89 QGraphicsSimpleTextItem *m_textItem;
90
91 };
125 };
92
126
93 QTCOMMERCIALCHART_END_NAMESPACE
127 QTCOMMERCIALCHART_END_NAMESPACE
@@ -40,7 +40,7 LegendScrollButton::ScrollButtonId LegendScrollButton::id()
40 void LegendScrollButton::mousePressEvent(QGraphicsSceneMouseEvent *event)
40 void LegendScrollButton::mousePressEvent(QGraphicsSceneMouseEvent *event)
41 {
41 {
42 Q_UNUSED(event);
42 Q_UNUSED(event);
43 m_ledgend->scrollButtonClicked(this);
43 //m_ledgend->scrollButtonClicked(this);
44 }
44 }
45
45
46
46
@@ -75,6 +75,7 Q_SIGNALS:
75 void hoverEnter();
75 void hoverEnter();
76 void hoverLeave();
76 void hoverLeave();
77 void changed();
77 void changed();
78 void selected();
78
79
79 private:
80 private:
80 friend class PieSliceData;
81 friend class PieSliceData;
@@ -66,13 +66,13 QTCOMMERCIALCHART_BEGIN_NAMESPACE
66 Constructs a chart object which is a child of a\a parent. Parameter \a wFlags is passed to the QGraphicsWidget constructor.
66 Constructs a chart object which is a child of a\a parent. Parameter \a wFlags is passed to the QGraphicsWidget constructor.
67 */
67 */
68 QChart::QChart(QGraphicsItem *parent, Qt::WindowFlags wFlags) : QGraphicsWidget(parent,wFlags),
68 QChart::QChart(QGraphicsItem *parent, Qt::WindowFlags wFlags) : QGraphicsWidget(parent,wFlags),
69 d_ptr(new QChartPrivate(this))
69 d_ptr(new QChartPrivate())
70 {
70 {
71 //setMinimumSize(200,200);
72 d_ptr->m_legend = new QLegend(this);
71 d_ptr->m_legend = new QLegend(this);
73 d_ptr->m_dataset = new ChartDataSet(this);
72 d_ptr->m_dataset = new ChartDataSet(this);
74 d_ptr->m_presenter = new ChartPresenter(this,d_ptr->m_dataset);
73 d_ptr->m_presenter = new ChartPresenter(this,d_ptr->m_dataset);
75 setMinimumSize(d_ptr->m_padding.left() * 3, d_ptr->m_padding.top() * 3);
74 d_ptr->m_presenter->setTheme(QChart::ChartThemeDefault,false);
75 //TODO:fix me setMinimumSize(d_ptr->m_padding.left() * 3, d_ptr->m_padding.top() * 3);
76 connect(d_ptr->m_dataset,SIGNAL(seriesAdded(QSeries*,Domain*)),d_ptr->m_legend,SLOT(handleSeriesAdded(QSeries*,Domain*)));
76 connect(d_ptr->m_dataset,SIGNAL(seriesAdded(QSeries*,Domain*)),d_ptr->m_legend,SLOT(handleSeriesAdded(QSeries*,Domain*)));
77 connect(d_ptr->m_dataset,SIGNAL(seriesRemoved(QSeries*)),d_ptr->m_legend,SLOT(handleSeriesRemoved(QSeries*)));
77 connect(d_ptr->m_dataset,SIGNAL(seriesRemoved(QSeries*)),d_ptr->m_legend,SLOT(handleSeriesRemoved(QSeries*)));
78 }
78 }
@@ -123,15 +123,15 void QChart::removeAllSeries()
123 */
123 */
124 void QChart::setBackgroundBrush(const QBrush& brush)
124 void QChart::setBackgroundBrush(const QBrush& brush)
125 {
125 {
126 d_ptr->createChartBackgroundItem();
126 d_ptr->m_presenter->createChartBackgroundItem();
127 d_ptr->m_backgroundItem->setBrush(brush);
127 d_ptr->m_presenter->m_backgroundItem->setBrush(brush);
128 d_ptr->m_backgroundItem->update();
128 d_ptr->m_presenter->m_backgroundItem->update();
129 }
129 }
130
130
131 QBrush QChart::backgroundBrush() const
131 QBrush QChart::backgroundBrush() const
132 {
132 {
133 if (!d_ptr->m_backgroundItem) return QBrush();
133 if (!d_ptr->m_presenter->m_backgroundItem) return QBrush();
134 return (d_ptr->m_backgroundItem)->brush();
134 return (d_ptr->m_presenter->m_backgroundItem)->brush();
135 }
135 }
136
136
137 /*!
137 /*!
@@ -139,15 +139,15 QBrush QChart::backgroundBrush() const
139 */
139 */
140 void QChart::setBackgroundPen(const QPen& pen)
140 void QChart::setBackgroundPen(const QPen& pen)
141 {
141 {
142 d_ptr->createChartBackgroundItem();
142 d_ptr->m_presenter->createChartBackgroundItem();
143 d_ptr->m_backgroundItem->setPen(pen);
143 d_ptr->m_presenter->m_backgroundItem->setPen(pen);
144 d_ptr->m_backgroundItem->update();
144 d_ptr->m_presenter->m_backgroundItem->update();
145 }
145 }
146
146
147 QPen QChart::backgroundPen() const
147 QPen QChart::backgroundPen() const
148 {
148 {
149 if (!d_ptr->m_backgroundItem) return QPen();
149 if (!d_ptr->m_presenter->m_backgroundItem) return QPen();
150 return d_ptr->m_backgroundItem->pen();
150 return d_ptr->m_presenter->m_backgroundItem->pen();
151 }
151 }
152
152
153 /*!
153 /*!
@@ -155,9 +155,9 QPen QChart::backgroundPen() const
155 */
155 */
156 void QChart::setTitle(const QString& title)
156 void QChart::setTitle(const QString& title)
157 {
157 {
158 d_ptr->createChartTitleItem();
158 d_ptr->m_presenter->createChartTitleItem();
159 d_ptr->m_titleItem->setText(title);
159 d_ptr->m_presenter->m_titleItem->setText(title);
160 d_ptr->updateLayout();
160 d_ptr->m_presenter->updateLayout();
161 }
161 }
162
162
163 /*!
163 /*!
@@ -165,8 +165,8 void QChart::setTitle(const QString& title)
165 */
165 */
166 QString QChart::title() const
166 QString QChart::title() const
167 {
167 {
168 if (d_ptr->m_titleItem)
168 if (d_ptr->m_presenter->m_titleItem)
169 return d_ptr->m_titleItem->text();
169 return d_ptr->m_presenter->m_titleItem->text();
170 else
170 else
171 return QString();
171 return QString();
172 }
172 }
@@ -176,9 +176,9 QString QChart::title() const
176 */
176 */
177 void QChart::setTitleFont(const QFont& font)
177 void QChart::setTitleFont(const QFont& font)
178 {
178 {
179 d_ptr->createChartTitleItem();
179 d_ptr->m_presenter->createChartTitleItem();
180 d_ptr->m_titleItem->setFont(font);
180 d_ptr->m_presenter->m_titleItem->setFont(font);
181 d_ptr->updateLayout();
181 d_ptr->m_presenter->updateLayout();
182 }
182 }
183
183
184 /*!
184 /*!
@@ -186,9 +186,9 void QChart::setTitleFont(const QFont& font)
186 */
186 */
187 void QChart::setTitleBrush(const QBrush &brush)
187 void QChart::setTitleBrush(const QBrush &brush)
188 {
188 {
189 d_ptr->createChartTitleItem();
189 d_ptr->m_presenter->createChartTitleItem();
190 d_ptr->m_titleItem->setBrush(brush);
190 d_ptr->m_presenter->m_titleItem->setBrush(brush);
191 d_ptr->updateLayout();
191 d_ptr->m_presenter->updateLayout();
192 }
192 }
193
193
194 /*!
194 /*!
@@ -196,8 +196,8 void QChart::setTitleBrush(const QBrush &brush)
196 */
196 */
197 QBrush QChart::titleBrush() const
197 QBrush QChart::titleBrush() const
198 {
198 {
199 if (!d_ptr->m_titleItem) return QBrush();
199 if (!d_ptr->m_presenter->m_titleItem) return QBrush();
200 return d_ptr->m_titleItem->brush();
200 return d_ptr->m_presenter->m_titleItem->brush();
201 }
201 }
202
202
203 /*!
203 /*!
@@ -267,9 +267,9 QLegend* QChart::legend() const
267 return d_ptr->m_legend;
267 return d_ptr->m_legend;
268 }
268 }
269
269
270 QRect QChart::padding() const
270 QRect QChart::margins() const
271 {
271 {
272 return d_ptr->m_padding;
272 return d_ptr->m_presenter->margins();
273 }
273 }
274
274
275
275
@@ -279,9 +279,8 QRect QChart::padding() const
279 void QChart::resizeEvent(QGraphicsSceneResizeEvent *event)
279 void QChart::resizeEvent(QGraphicsSceneResizeEvent *event)
280 {
280 {
281 d_ptr->m_rect = QRectF(QPoint(0,0),event->newSize());
281 d_ptr->m_rect = QRectF(QPoint(0,0),event->newSize());
282 d_ptr->updateLayout();
283 QGraphicsWidget::resizeEvent(event);
282 QGraphicsWidget::resizeEvent(event);
284 update();
283 d_ptr->m_presenter->setGeometry(d_ptr->m_rect);
285 }
284 }
286
285
287 /*!
286 /*!
@@ -302,46 +301,42 QChart::AnimationOptions QChart::animationOptions() const
302
301
303 void QChart::scrollLeft()
302 void QChart::scrollLeft()
304 {
303 {
305 d_ptr->m_presenter->scroll(-d_ptr->m_presenter->geometry().width()/(axisX()->ticksCount()-1),0);
304 d_ptr->m_presenter->scroll(-d_ptr->m_presenter->chartGeometry().width()/(axisX()->ticksCount()-1),0);
306 }
305 }
307
306
308 void QChart::scrollRight()
307 void QChart::scrollRight()
309 {
308 {
310 d_ptr->m_presenter->scroll(d_ptr->m_presenter->geometry().width()/(axisX()->ticksCount()-1),0);
309 d_ptr->m_presenter->scroll(d_ptr->m_presenter->chartGeometry().width()/(axisX()->ticksCount()-1),0);
311 }
310 }
312
311
313 void QChart::scrollUp()
312 void QChart::scrollUp()
314 {
313 {
315 d_ptr->m_presenter->scroll(0,d_ptr->m_presenter->geometry().width()/(axisY()->ticksCount()-1));
314 d_ptr->m_presenter->scroll(0,d_ptr->m_presenter->chartGeometry().width()/(axisY()->ticksCount()-1));
316 }
315 }
317
316
318 void QChart::scrollDown()
317 void QChart::scrollDown()
319 {
318 {
320 d_ptr->m_presenter->scroll(0,-d_ptr->m_presenter->geometry().width()/(axisY()->ticksCount()-1));
319 d_ptr->m_presenter->scroll(0,-d_ptr->m_presenter->chartGeometry().width()/(axisY()->ticksCount()-1));
321 }
320 }
322
321
323 void QChart::setBackgroundVisible(bool visible)
322 void QChart::setBackgroundVisible(bool visible)
324 {
323 {
325 d_ptr->createChartBackgroundItem();
324 d_ptr->m_presenter->createChartBackgroundItem();
326 d_ptr->m_backgroundItem->setVisible(visible);
325 d_ptr->m_presenter->m_backgroundItem->setVisible(visible);
327 }
326 }
328
327
329 bool QChart::isBackgroundVisible() const
328 bool QChart::isBackgroundVisible() const
330 {
329 {
331 if (!d_ptr->m_backgroundItem) return false;
330 if (!d_ptr->m_presenter->m_backgroundItem) return false;
332 return d_ptr->m_backgroundItem->isVisible();
331 return d_ptr->m_presenter->m_backgroundItem->isVisible();
333 }
332 }
334
333
335 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
334 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
336
335
337 QChartPrivate::QChartPrivate(QChart *parent):
336 QChartPrivate::QChartPrivate():
338 q_ptr(parent),
339 m_backgroundItem(0),
340 m_titleItem(0),
341 m_legend(0),
337 m_legend(0),
342 m_dataset(0),
338 m_dataset(0),
343 m_presenter(0),
339 m_presenter(0)
344 m_padding(QRect(50,50,0,0))
345 {
340 {
346
341
347 }
342 }
@@ -351,150 +346,6 QChartPrivate::~QChartPrivate()
351
346
352 }
347 }
353
348
354 void QChartPrivate::createChartBackgroundItem()
355 {
356 if (!m_backgroundItem) {
357 m_backgroundItem = new ChartBackground(q_ptr);
358 m_backgroundItem->setPen(Qt::NoPen);
359 m_backgroundItem->setZValue(ChartPresenter::BackgroundZValue);
360 }
361 }
362
363 void QChartPrivate::createChartTitleItem()
364 {
365 if (!m_titleItem) {
366 m_titleItem = new QGraphicsSimpleTextItem(q_ptr);
367 m_titleItem->setZValue(ChartPresenter::BackgroundZValue);
368 }
369 }
370
371 void QChartPrivate::updateLegendLayout()
372 {
373 //int legendPadding = m_chart->legend()->padding();
374 int legendPadding = 30;
375 QRectF rect = m_rect;
376
377 if ((m_legend->attachedToChart()) && (m_legend->isVisible())) {
378
379 // Reserve some space for legend
380 switch (m_legend->alignment()) {
381 case QLegend::AlignmentTop: {
382 rect.adjust(m_padding.left(),
383 m_padding.top() + legendPadding,
384 -m_padding.right(),
385 -m_padding.bottom());
386 break;
387 }
388 case QLegend::AlignmentBottom: {
389 rect.adjust(m_padding.left(),
390 m_padding.top(),
391 -m_padding.right(),
392 -m_padding.bottom() - legendPadding);
393 break;
394 }
395 case QLegend::AlignmentLeft: {
396 rect.adjust(m_padding.left() + legendPadding,
397 m_padding.top(),
398 -m_padding.right(),
399 -m_padding.bottom());
400 break;
401 }
402 case QLegend::AlignmentRight: {
403 rect.adjust(m_padding.left(),
404 m_padding.top(),
405 -m_padding.right() - legendPadding,
406 -m_padding.bottom());
407 break;
408 }
409 default: {
410 rect.adjust(m_padding.left(),
411 m_padding.top(),
412 -m_padding.right(),
413 -m_padding.bottom());
414 break;
415 }
416 }
417 } else {
418
419 rect.adjust(m_padding.left(),
420 m_padding.top(),
421 -m_padding.right(),
422 -m_padding.bottom());
423 }
424
425 QRectF plotRect = m_rect.adjusted(m_padding.left()
426 ,m_padding.top()
427 ,-m_padding.right()
428 ,-m_padding.bottom());
429 QRectF legendRect;
430
431 int padding = 0; // TODO: fix this
432 switch (m_legend->alignment())
433 {
434 case QLegend::AlignmentTop: {
435 legendRect = m_rect.adjusted(0,padding,0,-padding - plotRect.height());
436 break;
437 }
438 case QLegend::AlignmentBottom: {
439 legendRect = m_rect.adjusted(padding,padding + plotRect.height(),-padding,0);
440 break;
441 }
442 case QLegend::AlignmentLeft: {
443 legendRect = m_rect.adjusted(0,padding,-padding - plotRect.width(),-padding);
444 break;
445 }
446 case QLegend::AlignmentRight: {
447 legendRect = m_rect.adjusted(padding + plotRect.width(),padding,0,-padding);
448 break;
449 }
450 default: {
451 legendRect = plotRect;
452 break;
453 }
454 }
455
456 m_legend->setMaximumSize(legendRect.size());
457
458 qreal width = legendRect.width() - m_legend->size().width();
459 qreal height = legendRect.height() - m_legend->size().height();
460
461 QPointF pos = legendRect.topLeft();
462 if (width > 0) {
463 pos.setX(pos.x() + width/2);
464 }
465 if (height > 0) {
466 pos.setY(pos.y() + height/2);
467 }
468
469 m_legend->setPos(pos);
470 }
471
472 void QChartPrivate::updateLayout()
473 {
474 if (!m_rect.isValid()) return;
475
476 int padding = m_padding.top();
477 int backgroundPadding = m_presenter->backgroundPadding();
478
479 // recalculate title position
480 if (m_titleItem) {
481 QPointF center = m_rect.center() -m_titleItem->boundingRect().center();
482 m_titleItem->setPos(center.x(),m_rect.top()/2 + padding/2);
483 }
484
485 //recalculate background gradient
486 if (m_backgroundItem) {
487 m_backgroundItem->setRect(m_rect.adjusted(backgroundPadding,backgroundPadding, -backgroundPadding, -backgroundPadding));
488 }
489
490 // recalculate legend position
491 if (m_legend) {
492 if ((m_legend->attachedToChart()) && (m_legend->parentObject() == q_ptr)) {
493 updateLegendLayout();
494 }
495 }
496 }
497
498 #include "moc_qchart.cpp"
349 #include "moc_qchart.cpp"
499
350
500 QTCOMMERCIALCHART_END_NAMESPACE
351 QTCOMMERCIALCHART_END_NAMESPACE
@@ -99,8 +99,7 public:
99 QChartAxis* axisY() const;
99 QChartAxis* axisY() const;
100
100
101 QLegend* legend() const;
101 QLegend* legend() const;
102
102 QRect margins() const;
103 QRect padding() const;
104
103
105 protected:
104 protected:
106 void resizeEvent(QGraphicsSceneResizeEvent *event);
105 void resizeEvent(QGraphicsSceneResizeEvent *event);
@@ -108,6 +107,7 protected:
108 protected:
107 protected:
109 QScopedPointer<QChartPrivate> d_ptr;
108 QScopedPointer<QChartPrivate> d_ptr;
110 friend class QLegend;
109 friend class QLegend;
110 friend class ChartPresenter;
111 Q_DISABLE_COPY(QChart)
111 Q_DISABLE_COPY(QChart)
112 };
112 };
113
113
@@ -30,11 +30,9
30 #ifndef QCHART_P_H
30 #ifndef QCHART_P_H
31 #define QCHART_P_H
31 #define QCHART_P_H
32
32
33 #include "qchartaxis.h"
34 #include "qlegend.h"
33 #include "qlegend.h"
35 #include "chartpresenter_p.h"
34 #include "chartpresenter_p.h"
36 #include "chartdataset_p.h"
35 #include "chartdataset_p.h"
37 #include "chartbackground_p.h"
38
36
39 QTCOMMERCIALCHART_BEGIN_NAMESPACE
37 QTCOMMERCIALCHART_BEGIN_NAMESPACE
40
38
@@ -42,22 +40,13 class QChart;
42
40
43 struct QChartPrivate
41 struct QChartPrivate
44 {
42 {
45 QChartPrivate(QChart *parent);
43 QChartPrivate();
46 ~QChartPrivate();
44 ~QChartPrivate();
47
48 void createChartBackgroundItem();
49 void createChartTitleItem();
50 void updateLayout();
51 void updateLegendLayout();
52
53 QChart *q_ptr;
54 ChartBackground* m_backgroundItem;
55 QGraphicsSimpleTextItem* m_titleItem;
56 QRectF m_rect;
45 QRectF m_rect;
57 QLegend* m_legend;
46 QLegend* m_legend;
58 ChartDataSet *m_dataset;
47 ChartDataSet *m_dataset;
59 ChartPresenter *m_presenter;
48 ChartPresenter *m_presenter;
60 QRect m_padding;
49
61 };
50 };
62
51
63 QTCOMMERCIALCHART_END_NAMESPACE
52 QTCOMMERCIALCHART_END_NAMESPACE
@@ -116,7 +116,7 void QChartView::mousePressEvent(QMouseEvent *event)
116 {
116 {
117 if(d_ptr->m_rubberBand && d_ptr->m_rubberBand->isEnabled() && event->button() == Qt::LeftButton) {
117 if(d_ptr->m_rubberBand && d_ptr->m_rubberBand->isEnabled() && event->button() == Qt::LeftButton) {
118
118
119 int padding = d_ptr->m_chart->padding().top();
119 int padding = d_ptr->m_chart->margins().top();
120 QRect rect(padding, padding, width() - 2 * padding, height() - 2 * padding);
120 QRect rect(padding, padding, width() - 2 * padding, height() - 2 * padding);
121
121
122 if (rect.contains(event->pos())) {
122 if (rect.contains(event->pos())) {
@@ -138,7 +138,7 void QChartView::mousePressEvent(QMouseEvent *event)
138 void QChartView::mouseMoveEvent(QMouseEvent *event)
138 void QChartView::mouseMoveEvent(QMouseEvent *event)
139 {
139 {
140 if(d_ptr->m_rubberBand && d_ptr->m_rubberBand->isVisible()) {
140 if(d_ptr->m_rubberBand && d_ptr->m_rubberBand->isVisible()) {
141 int padding = d_ptr->m_chart->padding().top();
141 int padding = d_ptr->m_chart->margins().top();
142 QRect rect(padding, padding, width() - 2 * padding, height() - 2 * padding);
142 QRect rect(padding, padding, width() - 2 * padding, height() - 2 * padding);
143 int width = event->pos().x() - d_ptr->m_rubberBandOrigin.x();
143 int width = event->pos().x() - d_ptr->m_rubberBandOrigin.x();
144 int height = event->pos().y() - d_ptr->m_rubberBandOrigin.y();
144 int height = event->pos().y() - d_ptr->m_rubberBandOrigin.y();
@@ -22,7 +22,6
22 #include "qchart_p.h"
22 #include "qchart_p.h"
23 #include "qseries.h"
23 #include "qseries.h"
24 #include "legendmarker_p.h"
24 #include "legendmarker_p.h"
25 #include "legendscrollbutton_p.h"
26 #include "qxyseries.h"
25 #include "qxyseries.h"
27 #include "qlineseries.h"
26 #include "qlineseries.h"
28 #include "qareaseries.h"
27 #include "qareaseries.h"
@@ -35,8 +34,10
35 #include "qpieseries.h"
34 #include "qpieseries.h"
36 #include "qpieslice.h"
35 #include "qpieslice.h"
37 #include "chartpresenter_p.h"
36 #include "chartpresenter_p.h"
37 #include "scroller_p.h"
38 #include <QPainter>
38 #include <QPainter>
39 #include <QPen>
39 #include <QPen>
40 #include <QTimer>
40
41
41 #include <QGraphicsSceneEvent>
42 #include <QGraphicsSceneEvent>
42
43
@@ -86,45 +87,51 QTCOMMERCIALCHART_BEGIN_NAMESPACE
86 /*!
87 /*!
87 Constructs the legend object and sets the parent to \a parent
88 Constructs the legend object and sets the parent to \a parent
88 */
89 */
90
89 QLegend::QLegend(QChart *chart):QGraphicsWidget(chart),
91 QLegend::QLegend(QChart *chart):QGraphicsWidget(chart),
90 m_margin(5),
92 m_margin(5),
91 m_pos(0,0),
93 m_offsetX(0),
92 m_minimumSize(50,20), // TODO: magic numbers
94 m_offsetY(0),
93 m_maximumSize(150,100),
94 m_size(m_minimumSize),
95 m_brush(Qt::darkGray), // TODO: default should come from theme
95 m_brush(Qt::darkGray), // TODO: default should come from theme
96 m_alignment(QLegend::AlignmentTop),
96 m_alignment(QLegend::AlignmentTop),
97 mFirstMarker(0),
97 m_markers(new QGraphicsItemGroup(this)),
98 m_attachedToChart(true),
98 m_attachedToChart(true),
99 m_chart(chart)
99 m_chart(chart),
100 m_minWidth(0),
101 m_minHeight(0),
102 m_width(0),
103 m_height(0),
104 m_visible(false),
105 m_dirty(false),
106 m_scroller(new Scroller(this))
100 {
107 {
101 m_scrollButtonLeft = new LegendScrollButton(LegendScrollButton::ScrollButtonIdLeft, this);
102 m_scrollButtonRight = new LegendScrollButton(LegendScrollButton::ScrollButtonIdRight, this);
103 m_scrollButtonUp = new LegendScrollButton(LegendScrollButton::ScrollButtonIdUp, this);
104 m_scrollButtonDown = new LegendScrollButton(LegendScrollButton::ScrollButtonIdDown, this);
105 setZValue(ChartPresenter::LegendZValue);
108 setZValue(ChartPresenter::LegendZValue);
109 setFlags(QGraphicsItem::ItemClipsChildrenToShape);
106 }
110 }
107
111
108 /*!
112 /*!
109 Paints the legend to given \a painter. Paremeters \a option and \a widget arent used.
113 Paints the legend to given \a painter. Paremeters \a option and \a widget arent used.
110 */
114 */
115
111 void QLegend::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
116 void QLegend::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
112 {
117 {
113 Q_UNUSED(option)
118 Q_UNUSED(option)
114 Q_UNUSED(widget)
119 Q_UNUSED(widget)
120 if(!m_visible) return;
115
121
116 painter->setOpacity(opacity());
122 painter->setOpacity(opacity());
117 painter->setPen(m_pen);
123 painter->setPen(m_pen);
118 painter->setBrush(m_brush);
124 painter->setBrush(m_brush);
119 // painter->drawRect(boundingRect());
125 painter->drawRect(boundingRect());
120 }
126 }
121
127
122 /*!
128 /*!
123 Bounding rect of legend.
129 Bounding rect of legend.
124 */
130 */
131
125 QRectF QLegend::boundingRect() const
132 QRectF QLegend::boundingRect() const
126 {
133 {
127 return QRectF(m_pos,m_size);
134 return m_rect;
128 }
135 }
129
136
130 /*!
137 /*!
@@ -172,11 +179,10 QPen QLegend::pen() const
172 */
179 */
173 void QLegend::setAlignmnent(QLegend::Alignments alignment)
180 void QLegend::setAlignmnent(QLegend::Alignments alignment)
174 {
181 {
175 // if (!m_attachedToChart) {
182 if(m_alignment!=alignment && m_attachedToChart) {
176 m_alignment = alignment;
183 m_alignment = alignment;
177 updateLayout();
184 updateLayout();
178 m_chart->resize(m_chart->size());
185 }
179 // }
180 }
186 }
181
187
182 /*!
188 /*!
@@ -188,56 +194,6 QLegend::Alignments QLegend::alignment() const
188 }
194 }
189
195
190 /*!
196 /*!
191 Returns the maximum size of legend.
192 */
193 QSizeF QLegend::maximumSize() const
194 {
195 return m_maximumSize;
196 }
197
198 /*!
199 Sets the maximum \a size for legend. The legend can't grow bigger than this size. If there are
200 more series than legend can fit to this size, scroll buttons are displayed.
201 */
202 void QLegend::setMaximumSize(const QSizeF size)
203 {
204 m_maximumSize = size;
205 updateLayout();
206 }
207
208 /*!
209 Returns the current size of legend.
210 */
211 QSizeF QLegend::size() const
212 {
213 return m_size;
214 }
215
216 /*!
217 Sets the \a size of legend. If size is bigger than maximum size of legend, the legend is resized to the maximum size.
218 \sa setMmaximumSize()
219 */
220 void QLegend::setSize(const QSizeF size)
221 {
222 m_size = size;
223 if (m_size.width() > m_maximumSize.width()) {
224 m_size.setWidth(m_maximumSize.width());
225 }
226 if (m_size.height() > m_maximumSize.height()) {
227 m_size.setHeight(m_maximumSize.height());
228 }
229 }
230
231 /*!
232 Sets position of legend to \a pos
233 */
234 void QLegend::setPos(const QPointF &pos)
235 {
236 m_pos = pos;
237 updateLayout();
238 }
239
240 /*!
241 \internal \a series \a domain Should be called when series is added to chart.
197 \internal \a series \a domain Should be called when series is added to chart.
242 */
198 */
243 void QLegend::handleSeriesAdded(QSeries *series, Domain *domain)
199 void QLegend::handleSeriesAdded(QSeries *series, Domain *domain)
@@ -293,7 +249,11 void QLegend::handleSeriesAdded(QSeries *series, Domain *domain)
293 }
249 }
294 }
250 }
295
251
296 updateLayout();
252 // wait for all series added
253 if(!m_dirty){
254 QTimer::singleShot(0,this,SLOT(updateLayout()));
255 m_dirty=true;
256 }
297 }
257 }
298
258
299 /*!
259 /*!
@@ -330,17 +290,10 void QLegend::handleSeriesRemoved(QSeries *series)
330 void QLegend::handleAdded(QList<QPieSlice *> slices)
290 void QLegend::handleAdded(QList<QPieSlice *> slices)
331 {
291 {
332 QPieSeries* series = static_cast<QPieSeries *> (sender());
292 QPieSeries* series = static_cast<QPieSeries *> (sender());
333 foreach(QPieSlice* s, slices) {
293 foreach(QPieSlice* slice, slices) {
334 LegendMarker* marker = new LegendMarker(series, s, this);
294 PieLegendMarker* marker = new PieLegendMarker(series,slice, this);
335 marker->setName(s->label());
336 marker->setBrush(s->brush());
337 connect(marker, SIGNAL(clicked(QPieSlice*,Qt::MouseButton)),
338 this, SIGNAL(clicked(QPieSlice*,Qt::MouseButton)));
339 connect(s, SIGNAL(changed()), marker, SLOT(changed()));
340 connect(s, SIGNAL(destroyed()), marker, SLOT(deleteLater()));
341 connect(marker, SIGNAL(destroyed()), this, SLOT(handleMarkerDestroyed()));
295 connect(marker, SIGNAL(destroyed()), this, SLOT(handleMarkerDestroyed()));
342 m_markers.append(marker);
296 m_markers->addToGroup(marker);
343 childItems().append(marker);
344 }
297 }
345 updateLayout();
298 updateLayout();
346 }
299 }
@@ -361,36 +314,8 void QLegend::handleRemoved(QList<QPieSlice *> slices)
361 void QLegend::handleMarkerDestroyed()
314 void QLegend::handleMarkerDestroyed()
362 {
315 {
363 LegendMarker* m = static_cast<LegendMarker *> (sender());
316 LegendMarker* m = static_cast<LegendMarker *> (sender());
364 m_markers.removeOne(m);
317 delete m;
365 updateLayout();
318 // updateLayout();
366 }
367
368 /*!
369 \internal \a event Handles clicked signals from scroll buttons
370 */
371 void QLegend::scrollButtonClicked(LegendScrollButton *scrollButton)
372 {
373 Q_ASSERT(scrollButton);
374
375 switch (scrollButton->id()) {
376 case LegendScrollButton::ScrollButtonIdLeft:
377 case LegendScrollButton::ScrollButtonIdUp: {
378 // Lower limit is same in these cases
379 mFirstMarker--;
380 checkFirstMarkerBounds();
381 break;
382 }
383 case LegendScrollButton::ScrollButtonIdRight:
384 case LegendScrollButton::ScrollButtonIdDown: {
385 mFirstMarker++;
386 checkFirstMarkerBounds();
387 break;
388 }
389 default: {
390 break;
391 }
392 }
393 updateLayout();
394 }
319 }
395
320
396 /*!
321 /*!
@@ -412,7 +337,7 void QLegend::attachToChart()
412 /*!
337 /*!
413 Returns true, if legend is attached to chart.
338 Returns true, if legend is attached to chart.
414 */
339 */
415 bool QLegend::attachedToChart()
340 bool QLegend::isAttachedToChart()
416 {
341 {
417 return m_attachedToChart;
342 return m_attachedToChart;
418 }
343 }
@@ -422,13 +347,9 bool QLegend::attachedToChart()
422 */
347 */
423 void QLegend::appendMarkers(QAreaSeries* series)
348 void QLegend::appendMarkers(QAreaSeries* series)
424 {
349 {
425 LegendMarker* marker = new LegendMarker(series,this);
350 AreaLegendMarker* marker = new AreaLegendMarker(series,this);
426 connect(marker, SIGNAL(clicked(QSeries *, Qt::MouseButton)), this, SIGNAL(clicked(QSeries *, Qt::MouseButton)));
427 connect(marker, SIGNAL(destroyed()), this, SLOT(handleMarkerDestroyed()));
351 connect(marker, SIGNAL(destroyed()), this, SLOT(handleMarkerDestroyed()));
428 connect(series,SIGNAL(updated()),marker,SLOT(changed()));
352 m_markers->addToGroup(marker);
429 marker->changed();
430 m_markers.append(marker);
431 childItems().append(marker);
432 }
353 }
433
354
434 /*!
355 /*!
@@ -436,13 +357,9 void QLegend::appendMarkers(QAreaSeries* series)
436 */
357 */
437 void QLegend::appendMarkers(QXYSeries* series)
358 void QLegend::appendMarkers(QXYSeries* series)
438 {
359 {
439 LegendMarker* marker = new LegendMarker(series,this);
360 XYLegendMarker* marker = new XYLegendMarker(series,this);
440 connect(marker, SIGNAL(clicked(QSeries *, Qt::MouseButton)), this, SIGNAL(clicked(QSeries *, Qt::MouseButton)));
441 connect(marker, SIGNAL(destroyed()), this, SLOT(handleMarkerDestroyed()));
361 connect(marker, SIGNAL(destroyed()), this, SLOT(handleMarkerDestroyed()));
442 connect(series,SIGNAL(updated()),marker,SLOT(changed()));
362 m_markers->addToGroup(marker);
443 marker->changed();
444 m_markers.append(marker);
445 childItems().append(marker);
446 }
363 }
447
364
448 /*!
365 /*!
@@ -451,14 +368,9 void QLegend::appendMarkers(QXYSeries* series)
451 void QLegend::appendMarkers(QBarSeries *series)
368 void QLegend::appendMarkers(QBarSeries *series)
452 {
369 {
453 foreach(QBarSet* set, series->barSets()) {
370 foreach(QBarSet* set, series->barSets()) {
454 LegendMarker* marker = new LegendMarker(series, set, this);
371 BarLegendMarker* marker = new BarLegendMarker(series,set, this);
455 connect(marker, SIGNAL(clicked(QBarSet *, Qt::MouseButton)),
456 this, SIGNAL(clicked(QBarSet *, Qt::MouseButton)));
457 connect(set, SIGNAL(valueChanged()), marker, SLOT(changed()));
458 connect(marker, SIGNAL(destroyed()), this, SLOT(handleMarkerDestroyed()));
372 connect(marker, SIGNAL(destroyed()), this, SLOT(handleMarkerDestroyed()));
459 marker->changed();
373 m_markers->addToGroup(marker);
460 m_markers.append(marker);
461 childItems().append(marker);
462 }
374 }
463 }
375 }
464
376
@@ -468,15 +380,9 void QLegend::appendMarkers(QBarSeries *series)
468 void QLegend::appendMarkers(QPieSeries *series)
380 void QLegend::appendMarkers(QPieSeries *series)
469 {
381 {
470 foreach(QPieSlice* slice, series->slices()) {
382 foreach(QPieSlice* slice, series->slices()) {
471 LegendMarker* marker = new LegendMarker(series, slice, this);
383 PieLegendMarker* marker = new PieLegendMarker(series,slice, this);
472 connect(marker, SIGNAL(clicked(QPieSlice *, Qt::MouseButton)),
473 this, SIGNAL(clicked(QPieSlice *, Qt::MouseButton)));
474 connect(slice, SIGNAL(changed()), marker, SLOT(changed()));
475 connect(slice, SIGNAL(destroyed()), marker, SLOT(deleteLater()));
476 connect(marker, SIGNAL(destroyed()), this, SLOT(handleMarkerDestroyed()));
384 connect(marker, SIGNAL(destroyed()), this, SLOT(handleMarkerDestroyed()));
477 marker->changed();
385 m_markers->addToGroup(marker);
478 m_markers.append(marker);
479 childItems().append(marker);
480 }
386 }
481 }
387 }
482
388
@@ -486,10 +392,13 void QLegend::appendMarkers(QPieSeries *series)
486 void QLegend::deleteMarkers(QSeries *series)
392 void QLegend::deleteMarkers(QSeries *series)
487 {
393 {
488 // Search all markers that belong to given series and delete them.
394 // Search all markers that belong to given series and delete them.
489 foreach (LegendMarker *m, m_markers) {
395
490 if (m->series() == series) {
396 QList<QGraphicsItem *> items = m_markers->childItems();
491 m_markers.removeOne(m);
397
492 delete m;
398 foreach (QGraphicsItem *m, items) {
399 LegendMarker *marker = static_cast<LegendMarker*>(m);
400 if (marker->series() == series) {
401 delete marker;
493 }
402 }
494 }
403 }
495 }
404 }
@@ -499,251 +408,154 void QLegend::deleteMarkers(QSeries *series)
499 If items don't fit, sets the visibility of scroll buttons accordingly.
408 If items don't fit, sets the visibility of scroll buttons accordingly.
500 Causes legend to be resized.
409 Causes legend to be resized.
501 */
410 */
502 void QLegend::updateLayout()
411
412 void QLegend::setOffset(const QPointF& point)
503 {
413 {
504 // Calculate layout for markers and text
505 if (m_markers.count() <= 0) {
506 // Nothing to do
507 return;
508 }
509
414
510 checkFirstMarkerBounds();
415 switch(m_alignment) {
511
416
512 switch (m_alignment)
417 case AlignmentTop:
513 {
418 case AlignmentBottom: {
514 // Both cases organise items horizontally
419 if(m_width<=m_rect.width()) return;
515 case QLegend::AlignmentBottom:
420
516 case QLegend::AlignmentTop: {
421 if (point.x() != m_offsetX) {
517 layoutHorizontal();
422 m_offsetX = qBound(0.0, point.x(), m_width - m_rect.width());
518 break;
423 m_markers->setPos(-m_offsetX,m_rect.top());
519 }
424 }
520 // Both cases organize items vertically
521 case QLegend::AlignmentLeft:
522 case QLegend::AlignmentRight: {
523 layoutVertical();
524 break;
425 break;
525 }
426 }
526 default: {
427 case AlignmentLeft:
428 case AlignmentRight: {
429
430 if(m_height<=m_rect.height()) return;
431
432 if (point.y() != m_offsetY) {
433 m_offsetY = qBound(0.0, point.y(), m_height - m_rect.height());
434 m_markers->setPos(m_rect.left(),-m_offsetY);
435 }
527 break;
436 break;
528 }
437 }
529 }
438 }
530
531 }
439 }
532
440
533 /*!
441 QPointF QLegend::offset() const
534 \internal Organizes markers horizontally.
442 {
535 Causes legend to be resized.
443 return QPointF(m_offsetX,m_offsetY);
536 */
537 void QLegend::layoutHorizontal()
538 {
539 // Find out widest item.
540 QSizeF markerMaxSize = maximumMarkerSize();
541 // Use max height as scroll button size
542 rescaleScrollButtons(QSize(markerMaxSize.height() ,markerMaxSize.height()));
543
544 qreal totalWidth = 0;
545 qreal totalHeight = 0;
546
547 qreal xStep = markerMaxSize.width();
548 qreal x = m_pos.x() + m_margin;
549 qreal y = m_pos.y() + m_margin;
550 int column = 0;
551 int maxColumns = 1;
552 qreal scrollButtonWidth = 0;
553
554 // Set correct visibility for scroll scrollbuttons
555 if (scrollButtonsVisible()) {
556 m_scrollButtonLeft->setVisible(true);
557 m_scrollButtonRight->setVisible(true);
558 // scrollbuttons visible, so add their width to total width
559 totalWidth += (m_scrollButtonLeft->boundingRect().width() + m_margin) * 2;
560 scrollButtonWidth = m_scrollButtonLeft->boundingRect().width() + m_margin;
561 // start position changes by scrollbutton width
562 x += scrollButtonWidth;
563 } else {
564 m_scrollButtonLeft->setVisible(false);
565 m_scrollButtonRight->setVisible(false);
566 }
444 }
567 m_scrollButtonUp->setVisible(false);
568 m_scrollButtonDown->setVisible(false);
569
445
570 for (int i=0; i < m_markers.count(); i++) {
446 // this function runs first to set min max values
571 LegendMarker *m = m_markers.at(i);
447 void QLegend::updateLayout()
572 if (i < mFirstMarker) {
448 {
573 // Markers before first are not visible.
449 m_dirty=false;
574 m->setVisible(false);
450 m_offsetX=0;
575 } else {
451 QList<QGraphicsItem *> items = m_markers->childItems();
576 if ((x + xStep + scrollButtonWidth + m_margin) > (m_pos.x() + m_maximumSize.width())) {
577 // This marker would go outside legend rect.
578 m->setVisible(false);
579 } else {
580 // This marker is ok
581 m->setVisible(true);
582 m->setPos(x, y);
583 x += xStep;
584 column++;
585 }
586 }
587 maxColumns = column;
588 }
589
452
590 m_scrollButtonLeft->setPos(m_pos.x() + m_margin, y);
453 if(items.isEmpty()) return;
591 m_scrollButtonRight->setPos(x + m_margin, y);
592
454
593 totalWidth += maxColumns * markerMaxSize.width() + m_margin * 2;
455 m_minWidth=0;
594 totalHeight = markerMaxSize.height() + m_margin * 2;
456 m_minHeight=0;
595
457
596 m_size.setWidth(totalWidth);
458 switch(m_alignment) {
597 m_size.setHeight(totalHeight);
598 }
599
459
600 /*!
460 case AlignmentTop:
601 \internal Organizes markers vertically.
461 case AlignmentBottom: {
602 Causes legend to be resized.
462 QPointF point = m_rect.topLeft();
603 */
463 m_width = 0;
604 void QLegend::layoutVertical()
464 foreach (QGraphicsItem *item, items) {
605 {
465 item->setPos(point.x(),m_rect.height()/2 -item->boundingRect().height()/2);
606 // Find out widest item.
466 const QRectF& rect = item->boundingRect();
607 QSizeF markerMaxSize = maximumMarkerSize();
467 qreal w = rect.width();
608 // Use max height as scroll button size
468 m_minWidth=qMax(m_minWidth,w);
609 rescaleScrollButtons(QSize(markerMaxSize.height() ,markerMaxSize.height()));
469 m_minHeight=qMax(m_minHeight,rect.height());
610
470 m_width+=w;
611 qreal totalWidth = 0;
471 point.setX(point.x() + w);
612 qreal totalHeight = 0;
613
614 qreal yStep = markerMaxSize.height();
615 qreal x = m_pos.x() + m_margin;
616 qreal y = m_pos.y() + m_margin;
617 int row = 1;
618 int maxRows = 1;
619 qreal scrollButtonHeight = 0;
620
621 // Set correct visibility for scroll scrollbuttons
622 if (scrollButtonsVisible()) {
623 m_scrollButtonUp->setVisible(true);
624 m_scrollButtonDown->setVisible(true);
625 totalHeight += (m_scrollButtonUp->boundingRect().height() + m_margin) * 2; // scrollbuttons visible, so add their height to total height
626 scrollButtonHeight = m_scrollButtonUp->boundingRect().height();
627 y += scrollButtonHeight + m_margin; // start position changes by scrollbutton height
628 } else {
629 m_scrollButtonUp->setVisible(false);
630 m_scrollButtonDown->setVisible(false);
631 }
472 }
632 m_scrollButtonLeft->setVisible(false);
473 if(m_width<m_rect.width()){
633 m_scrollButtonRight->setVisible(false);
474 m_markers->setPos(m_rect.width()/2-m_width/2,m_rect.top());
634
635 for (int i=0; i < m_markers.count(); i++) {
636 LegendMarker* m = m_markers.at(i);
637 if (i < mFirstMarker) {
638 // Markers before first are not visible.
639 m->setVisible(false);
640 } else {
475 }else{
641 if ((y + yStep + scrollButtonHeight) > (m_pos.y() + m_maximumSize.height())) {
476 m_markers->setPos(m_rect.topLeft());
642 // This marker would go outside legend rect.
477 }
643 m->setVisible(false);
478 m_height=m_minHeight;
479 }
480 break;
481 case AlignmentLeft:
482 case AlignmentRight:{
483 QPointF point = m_rect.topLeft();
484 m_height = 0;
485 foreach (QGraphicsItem *item, items) {
486 item->setPos(point);
487 const QRectF& rect = item->boundingRect();
488 qreal h = rect.height();
489 m_minWidth=qMax(m_minWidth,rect.width());
490 m_minHeight=qMax(m_minHeight,h);
491 m_height+=h;
492 point.setY(point.y() + h);
493 }
494 if(m_height<m_rect.height()){
495 m_markers->setPos(m_rect.left(),m_rect.height()/2-m_height/2);
644 } else {
496 }else{
645 // This marker is ok
497 m_markers->setPos(m_rect.topLeft());
646 m->setVisible(true);
647 m->setPos(x, y);
648 y += yStep;
649 row++;
650 }
498 }
499 m_width=m_minWidth;
651 }
500 }
652 maxRows = row;
501 break;
653 }
502 }
654
503
655 m_scrollButtonUp->setPos(m_pos.x() + m_margin, m_pos.y() + m_margin);
504 m_chart->d_ptr->m_presenter->updateLayout(); //TODO fixme;
656 m_scrollButtonDown->setPos(m_pos.x() + m_margin, y + m_margin);
657
658 totalWidth += markerMaxSize.width() + m_margin * 2;
659 totalHeight = maxRows * markerMaxSize.height() + m_margin * 4 + scrollButtonHeight; // TODO: check this
660
661 m_size.setWidth(totalWidth);
662 m_size.setHeight(totalHeight);
663 }
505 }
664
506
665 /*!
507 void QLegend::setBackgroundVisible(bool visible)
666 \internal Sets the size of scroll buttons to \a size
667 */
668 void QLegend::rescaleScrollButtons(const QSize &size)
669 {
508 {
670 QPolygonF left;
509 if(m_visible!=visible)
671 left << QPointF(size.width(), 0) << QPointF(0, size.height() / 2) << QPointF(size.width(), size.height());
672 QPolygonF right;
673 right << QPointF(0, 0) << QPointF(size.width(), size.height() / 2) << QPointF(0, size.height());
674 QPolygonF up;
675 up << QPointF(0, size.height()) << QPointF(size.width() / 2,0) << QPointF(size.width(), size.height());
676 QPolygonF down;
677 down << QPointF(0, 0) << QPointF(size.width() / 2, size.height()) << QPointF(size.width(), 0);
678
679 m_scrollButtonLeft->setPolygon(left);
680 m_scrollButtonRight->setPolygon(right);
681 m_scrollButtonUp->setPolygon(up);
682 m_scrollButtonDown->setPolygon(down);
683 }
684
685 /*!
686 \internal Finds out maximum size of single marker. Marker sizes depend on series names.
687 */
688 QSizeF QLegend::maximumMarkerSize()
689 {
510 {
690 QSizeF max(0,0);
511 m_visible=visible;
691 foreach (LegendMarker* m, m_markers) {
512 update();
692 if (m->boundingRect().width() > max.width())
693 max.setWidth(m->boundingRect().width());
694 if (m->boundingRect().height() > max.height())
695 max.setHeight(m->boundingRect().height());
696 }
513 }
697 return max;
698 }
514 }
699
515
700 /*!
516 bool QLegend::isBackgroundVisible() const
701 \internal Checks that first marker is in acceptable bounds. Bounds range from 0 to (maximum number of markers - visible markers)
702 If scrollbuttons are visible, they affect the number of visible markers.
703 */
704 void QLegend::checkFirstMarkerBounds()
705 {
517 {
706 if ((m_alignment == QLegend::AlignmentLeft) || (m_alignment == QLegend::AlignmentRight)) {
518 return m_visible;
707 // Bounds limited by height.
708 int max;
709 if (scrollButtonsVisible()) {
710 max = (m_maximumSize.height() - m_scrollButtonLeft->boundingRect().height() * 2 - m_margin * 4) / maximumMarkerSize().height();
711 } else {
712 max = m_maximumSize.height() / maximumMarkerSize().height();
713 }
519 }
714
520
715 if (mFirstMarker > m_markers.count() - max)
521 void QLegend::resizeEvent(QGraphicsSceneResizeEvent *event)
716 mFirstMarker = m_markers.count() - max;
522 {
717 } else {
523 const QRectF& rect = QRectF(QPoint(0,0),event->newSize());
718 // Bounds limited by width
524 QGraphicsWidget::resizeEvent(event);
719 int max;
525 if(m_rect != rect){
720 if (scrollButtonsVisible()) {
526 m_rect = rect;
721 max = (m_maximumSize.width() - m_scrollButtonLeft->boundingRect().width() * 2 - m_margin*4) / maximumMarkerSize().width();
527 updateLayout();
722 } else {
723 max = m_maximumSize.width() / maximumMarkerSize().width();
724 }
528 }
725
726 if (mFirstMarker > m_markers.count() - max)
727 mFirstMarker = m_markers.count() - max;
728 }
529 }
729
530
730 if (mFirstMarker < 0)
531 void QLegend::hideEvent(QHideEvent *event)
731 mFirstMarker = 0;
532 {
533 QGraphicsWidget::hideEvent(event);
534 setEnabled(false);
535 updateLayout();
732 }
536 }
733
537
734 /*!
538 void QLegend::showEvent(QShowEvent *event)
735 \internal Helper function. Visibility of scroll buttons isn't quite obvious, so helper function clarifies the logic.
736 */
737 bool QLegend::scrollButtonsVisible()
738 {
539 {
739 // Just a helper to clarify, what the magic below means :)
540 QGraphicsWidget::showEvent(event);
740 if ((m_alignment == QLegend::AlignmentTop) || (m_alignment == QLegend::AlignmentBottom)) {
541 setEnabled(true);
741 return (maximumMarkerSize().width() * m_markers.count() + m_margin * 2 > m_maximumSize.width());
542 updateLayout();
742 } else if ((m_alignment == QLegend::AlignmentLeft) || (m_alignment == QLegend::AlignmentRight)) {
743 return (maximumMarkerSize().height() * m_markers.count() + m_margin * 2 > m_maximumSize.height());
744 }
543 }
745
544
746 return (maximumMarkerSize().height() * m_markers.count() + m_margin * 2 > m_maximumSize.height());
545 void QLegend::mousePressEvent(QGraphicsSceneMouseEvent* event)
546 {
547 //Q_UNUSED(event);
548 m_scroller->mousePressEvent(event);
549 }
550 void QLegend::mouseMoveEvent(QGraphicsSceneMouseEvent* event)
551 {
552 //Q_UNUSED(event);
553 m_scroller->mouseMoveEvent(event);
554 }
555 void QLegend::mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
556 {
557 //Q_UNUSED(event);
558 m_scroller->mouseReleaseEvent(event);
747 }
559 }
748
560
749 #include "moc_qlegend.cpp"
561 #include "moc_qlegend.cpp"
@@ -39,6 +39,7 class QAreaSeries;
39 class LegendScrollButton;
39 class LegendScrollButton;
40 class QSeries;
40 class QSeries;
41 class QChart;
41 class QChart;
42 class Scroller;
42
43
43 class QTCOMMERCIALCHART_EXPORT QLegend : public QGraphicsWidget
44 class QTCOMMERCIALCHART_EXPORT QLegend : public QGraphicsWidget
44 {
45 {
@@ -71,25 +72,27 public:
71 void setAlignmnent(QLegend::Alignments alignment);
72 void setAlignmnent(QLegend::Alignments alignment);
72 QLegend::Alignments alignment() const;
73 QLegend::Alignments alignment() const;
73
74
74 QSizeF maximumSize() const;
75 void setMaximumSize(const QSizeF size);
76
77 QSizeF size() const;
78 void setSize(const QSizeF size);
79 void setPos(const QPointF &pos);
80
81 void scrollButtonClicked(LegendScrollButton *scrollButton);
82
75
83 void detachFromChart();
76 void detachFromChart();
84 void attachToChart();
77 void attachToChart();
85 bool attachedToChart();
78 bool isAttachedToChart();
79
80 qreal minWidht() const { return m_minWidth;}
81 qreal minHeight() const { return m_minHeight;}
86
82
87 Q_SIGNALS:
83 void setBackgroundVisible(bool visible);
88 // for interactions.
84 bool isBackgroundVisible() const;
89 void clicked(QSeries *series, Qt::MouseButton button);
85
90 void clicked(QBarSet *barset, Qt::MouseButton button);
86 void setOffset(const QPointF& point);
91 void clicked(QPieSlice *slice, Qt::MouseButton button);
87 QPointF offset() const;
92 void legendGeometryChanged();
88
89 protected:
90 void resizeEvent(QGraphicsSceneResizeEvent *event);
91 void hideEvent(QHideEvent *event);
92 void showEvent(QShowEvent *event);
93 void mousePressEvent(QGraphicsSceneMouseEvent* event);
94 void mouseMoveEvent(QGraphicsSceneMouseEvent* event);
95 void mouseReleaseEvent(QGraphicsSceneMouseEvent* event);
93
96
94 public Q_SLOTS:
97 public Q_SLOTS:
95 // PIMPL --->
98 // PIMPL --->
@@ -108,36 +111,39 private:
108 void appendMarkers(QBarSeries *series);
111 void appendMarkers(QBarSeries *series);
109 void appendMarkers(QPieSeries *series);
112 void appendMarkers(QPieSeries *series);
110 void deleteMarkers(QSeries *series);
113 void deleteMarkers(QSeries *series);
114
115
116
117
118 private Q_SLOTS:
111 void updateLayout();
119 void updateLayout();
112 void layoutHorizontal();
120 void scroll();
113 void layoutVertical();
114 void rescaleScrollButtons(const QSize &size);
115 QSizeF maximumMarkerSize();
116 void checkFirstMarkerBounds();
117 bool scrollButtonsVisible();
118
121
122 private:
119 qreal m_margin;
123 qreal m_margin;
120 QPointF m_pos;
121 QSizeF m_minimumSize;
122 QSizeF m_maximumSize;
123 QSizeF m_size;
124
124
125 QList<LegendMarker *> m_markers;
125 QRectF m_rect;
126 qreal m_offsetX;
127 qreal m_offsetY;
128
129 //QList<LegendMarker *> m_markers;
126
130
127 QBrush m_brush;
131 QBrush m_brush;
128 QPen m_pen;
132 QPen m_pen;
129 QLegend::Alignments m_alignment;
133 QLegend::Alignments m_alignment;
134 QGraphicsItemGroup* m_markers;
130
135
131 int mFirstMarker;
132
133 LegendScrollButton *m_scrollButtonLeft;
134 LegendScrollButton *m_scrollButtonRight;
135 LegendScrollButton *m_scrollButtonUp;
136 LegendScrollButton *m_scrollButtonDown;
137
136
138 bool m_attachedToChart;
137 bool m_attachedToChart;
139
138
140 QChart *m_chart;
139 QChart *m_chart;
140 qreal m_minWidth;
141 qreal m_minHeight;
142 qreal m_width;
143 qreal m_height;
144 bool m_visible;
145 bool m_dirty;
146 Scroller* m_scroller;
141 friend class QChart;
147 friend class QChart;
142 // <--- PIMPL
148 // <--- PIMPL
143 };
149 };
@@ -19,7 +19,8 SOURCES += \
19 $$PWD/legendmarker.cpp \
19 $$PWD/legendmarker.cpp \
20 $$PWD/legendscrollbutton.cpp \
20 $$PWD/legendscrollbutton.cpp \
21 $$PWD/chartbackground.cpp \
21 $$PWD/chartbackground.cpp \
22 $$PWD/chart.cpp
22 $$PWD/chart.cpp \
23 $$PWD/scroller.cpp
23 PRIVATE_HEADERS += \
24 PRIVATE_HEADERS += \
24 $$PWD/chartdataset_p.h \
25 $$PWD/chartdataset_p.h \
25 $$PWD/chartitem_p.h \
26 $$PWD/chartitem_p.h \
@@ -32,7 +33,8 PRIVATE_HEADERS += \
32 $$PWD/chart_p.h \
33 $$PWD/chart_p.h \
33 $$PWD/chartconfig_p.h \
34 $$PWD/chartconfig_p.h \
34 $$PWD/qchart_p.h \
35 $$PWD/qchart_p.h \
35 $$PWD/qchartview_p.h
36 $$PWD/qchartview_p.h \
37 $$PWD/scroller_p.h
36 PUBLIC_HEADERS += \
38 PUBLIC_HEADERS += \
37 $$PWD/qchart.h \
39 $$PWD/qchart.h \
38 $$PWD/qchartglobal.h \
40 $$PWD/qchartglobal.h \
@@ -75,6 +75,7 private Q_SLOTS:
75
75
76 Q_SIGNALS:
76 Q_SIGNALS:
77 void clicked(const QPointF &point);
77 void clicked(const QPointF &point);
78 void selected();
78 void updated();
79 void updated();
79 void pointReplaced(int index);
80 void pointReplaced(int index);
80 void pointRemoved(int index);
81 void pointRemoved(int index);
@@ -131,7 +131,7 void tst_QChartView::rubberBand()
131 QFETCH(int, maxY);
131 QFETCH(int, maxY);
132
132
133 m_view->setRubberBand(rubberBand);
133 m_view->setRubberBand(rubberBand);
134 QRect padding = m_view->chart()->padding();
134 QRect padding = m_view->chart()->margins();
135 QCOMPARE(m_view->rubberBand(), rubberBand);
135 QCOMPARE(m_view->rubberBand(), rubberBand);
136
136
137 QLineSeries* line = new QLineSeries();
137 QLineSeries* line = new QLineSeries();
@@ -186,7 +186,7 void tst_QChartView::keys()
186 QFETCH(int, Xcount);
186 QFETCH(int, Xcount);
187 QFETCH(int, Ycount);
187 QFETCH(int, Ycount);
188
188
189 QRect padding = m_view->chart()->padding();
189 QRect padding = m_view->chart()->margins();
190
190
191 QLineSeries* line = new QLineSeries();
191 QLineSeries* line = new QLineSeries();
192 *line << QPointF(0, 0) << QPointF(100, 100);
192 *line << QPointF(0, 0) << QPointF(100, 100);
General Comments 0
You need to be logged in to leave comments. Login now