##// END OF EJS Templates
better legend detach layout. updated legend example
sauimone -
r1444:0ed586503264
parent child
Show More
@@ -1,149 +1,224
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2012 Digia Plc
3 ** Copyright (C) 2012 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
6 **
7 ** This file is part of the Qt Commercial Charts Add-on.
7 ** This file is part of the Qt Commercial Charts Add-on.
8 **
8 **
9 ** $QT_BEGIN_LICENSE$
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Commercial licenses may use this file in
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
13 ** a written agreement between you and Digia.
14 **
14 **
15 ** If you have questions regarding the use of this file, please use
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
17 ** $QT_END_LICENSE$
18 **
18 **
19 ****************************************************************************/
19 ****************************************************************************/
20
20
21 #include "mainwidget.h"
21 #include "mainwidget.h"
22 #include <QChart>
22 #include <QChart>
23 #include <QChartView>
23 #include <QChartView>
24 #include <QPushButton>
24 #include <QPushButton>
25 #include <QLabel>
25 #include <QLabel>
26 #include <QDebug>
26 #include <QDebug>
27 #include <QBarSet>
27 #include <QBarSet>
28 #include <QBarSeries>
28 #include <QBarSeries>
29 #include <QLegend>
29 #include <QLegend>
30 #include <QFormLayout>
30
31
31 QTCOMMERCIALCHART_USE_NAMESPACE
32 QTCOMMERCIALCHART_USE_NAMESPACE
32
33
33 MainWidget::MainWidget(QWidget *parent) :
34 MainWidget::MainWidget(QWidget *parent) :
34 QWidget(parent)
35 QWidget(parent)
35 {
36 {
36 // Create buttons for ui
37 // Create buttons for ui
37 m_buttonLayout = new QGridLayout();
38 m_buttonLayout = new QGridLayout();
38 QPushButton *detachLegendButton = new QPushButton("detach legend");
39 QPushButton *detachLegendButton = new QPushButton("detach legend");
39 connect(detachLegendButton, SIGNAL(clicked()), this, SLOT(detachLegend()));
40 connect(detachLegendButton, SIGNAL(clicked()), this, SLOT(detachLegend()));
40 m_buttonLayout->addWidget(detachLegendButton, 0, 0);
41 m_buttonLayout->addWidget(detachLegendButton, 0, 0);
41 QPushButton *attachLegendButton = new QPushButton("attach legend");
42 QPushButton *attachLegendButton = new QPushButton("attach legend");
42 connect(attachLegendButton, SIGNAL(clicked()), this, SLOT(attachLegend()));
43 connect(attachLegendButton, SIGNAL(clicked()), this, SLOT(attachLegend()));
43 m_buttonLayout->addWidget(attachLegendButton, 1, 0);
44 m_buttonLayout->addWidget(attachLegendButton, 1, 0);
44
45
45 QPushButton *addSetButton = new QPushButton("add barset");
46 QPushButton *addSetButton = new QPushButton("add barset");
46 connect(addSetButton, SIGNAL(clicked()), this, SLOT(addBarset()));
47 connect(addSetButton, SIGNAL(clicked()), this, SLOT(addBarset()));
47 m_buttonLayout->addWidget(addSetButton, 2, 0);
48 m_buttonLayout->addWidget(addSetButton, 2, 0);
48 QPushButton *removeBarsetButton = new QPushButton("remove barset");
49 QPushButton *removeBarsetButton = new QPushButton("remove barset");
49 connect(removeBarsetButton, SIGNAL(clicked()), this, SLOT(removeBarset()));
50 connect(removeBarsetButton, SIGNAL(clicked()), this, SLOT(removeBarset()));
50 m_buttonLayout->addWidget(removeBarsetButton, 3, 0);
51 m_buttonLayout->addWidget(removeBarsetButton, 3, 0);
51
52
53 QPushButton *leftButton = new QPushButton("Align legend left");
54 connect(leftButton, SIGNAL(clicked()), this, SLOT(setLegendLeft()));
55 m_buttonLayout->addWidget(leftButton, 4, 0);
56
57 QPushButton *rightButton = new QPushButton("Align legend right");
58 connect(rightButton, SIGNAL(clicked()), this, SLOT(setLegendRight()));
59 m_buttonLayout->addWidget(rightButton, 5, 0);
60
61 QPushButton *topButton = new QPushButton("Align legend top");
62 connect(topButton, SIGNAL(clicked()), this, SLOT(setLegendTop()));
63 m_buttonLayout->addWidget(topButton, 6, 0);
64
65 QPushButton *bottomButton = new QPushButton("Align legend bottom");
66 connect(bottomButton, SIGNAL(clicked()), this, SLOT(setLegendBottom()));
67 m_buttonLayout->addWidget(bottomButton, 7, 0);
68
69 m_legendPosX = new QDoubleSpinBox();
70 m_legendPosY = new QDoubleSpinBox();
71 m_legendWidth = new QDoubleSpinBox();
72 m_legendHeight = new QDoubleSpinBox();
73
74 connect(m_legendPosX, SIGNAL(valueChanged(double)), this, SLOT(updateLegendLayout()));
75 connect(m_legendPosY, SIGNAL(valueChanged(double)), this, SLOT(updateLegendLayout()));
76 connect(m_legendWidth, SIGNAL(valueChanged(double)), this, SLOT(updateLegendLayout()));
77 connect(m_legendHeight, SIGNAL(valueChanged(double)), this, SLOT(updateLegendLayout()));
78
79 QFormLayout* legendLayout = new QFormLayout();
80 legendLayout->addRow("Horizontal position", m_legendPosX);
81 legendLayout->addRow("Vertical position", m_legendPosY);
82 legendLayout->addRow("Width", m_legendWidth);
83 legendLayout->addRow("Height", m_legendHeight);
84 m_legendSettings = new QGroupBox("Detached legend");
85 m_legendSettings->setLayout(legendLayout);
86 m_buttonLayout->addWidget(m_legendSettings);
87 m_legendSettings->setVisible(false);
88
52 // Create chart view with the chart
89 // Create chart view with the chart
53 //![1]
90 //![1]
54 m_chart = new QChart();
91 m_chart = new QChart();
55 m_chartView = new QChartView(m_chart, this);
92 m_chartView = new QChartView(m_chart, this);
56 m_chartView->setRubberBand(QChartView::HorizonalRubberBand);
57 //![1]
93 //![1]
58
94
59 // Create custom scene and view, where detached legend will be drawn
60 //![2]
61 m_customView = new QGraphicsView(this);
62 m_customScene = new QGraphicsScene(this);
63 m_customView->setScene(m_customScene);
64 //![2]
65
66 // Create layout for grid and detached legend
95 // Create layout for grid and detached legend
67 m_mainLayout = new QGridLayout();
96 m_mainLayout = new QGridLayout();
68 m_mainLayout->addLayout(m_buttonLayout, 0, 0);
97 m_mainLayout->addLayout(m_buttonLayout, 0, 0);
69 m_mainLayout->addWidget(m_chartView, 0, 1, 3, 1);
98 m_mainLayout->addWidget(m_chartView, 0, 1, 3, 1);
70 m_mainLayout->addWidget(m_customView, 0, 2, 3, 1);
71 setLayout(m_mainLayout);
99 setLayout(m_mainLayout);
72
100
73 createSeries();
101 createSeries();
74 }
102 }
75
103
76 void MainWidget::createSeries()
104 void MainWidget::createSeries()
77 {
105 {
78 //![3]
106 //![3]
79 m_series = new QBarSeries();
107 m_series = new QBarSeries();
80 addBarset();
108 addBarset();
81 addBarset();
109 addBarset();
82 addBarset();
110 addBarset();
83 addBarset();
111 addBarset();
84
112
85 m_chart->addSeries(m_series);
113 m_chart->addSeries(m_series);
86 m_chart->setTitle("Legend detach example");
114 m_chart->setTitle("Legend detach example");
87
115
88 m_chart->legend()->setVisible(true);
116 m_chart->legend()->setVisible(true);
89 m_chart->legend()->setAlignment(Qt::AlignBottom);
117 m_chart->legend()->setAlignment(Qt::AlignBottom);
90 m_chart->axisY()->setNiceNumbersEnabled(true);
118 m_chart->axisY()->setNiceNumbersEnabled(true);
91
119
92 m_chartView->setRenderHint(QPainter::Antialiasing);
120 m_chartView->setRenderHint(QPainter::Antialiasing);
93 //![3]
121 //![3]
94 }
122 }
95
123
124 void MainWidget::showLegendSpinbox()
125 {
126 m_legendSettings->setVisible(true);
127 QRectF chartViewRect = m_chartView->rect();
128 QRectF legendRect = m_chart->legend()->boundingRect();
129
130 m_legendPosX->setMinimum(0);
131 m_legendPosX->setMaximum(chartViewRect.width());
132 m_legendPosX->setValue(150);
133
134 m_legendPosY->setMinimum(0);
135 m_legendPosY->setMaximum(chartViewRect.height());
136 m_legendPosY->setValue(150);
137
138 m_legendWidth->setMinimum(0);
139 m_legendWidth->setMaximum(chartViewRect.width());
140 m_legendWidth->setValue(150);
141
142 m_legendHeight->setMinimum(0);
143 m_legendHeight->setMaximum(chartViewRect.height());
144 m_legendHeight->setValue(64);
145 }
146
147 void MainWidget::hideLegendSpinbox()
148 {
149 m_legendSettings->setVisible(false);
150 }
151
152
96 void MainWidget::detachLegend()
153 void MainWidget::detachLegend()
97 {
154 {
98 // Detach legend from chart and
99 // put legend to our custom scene
100 //![4]
155 //![4]
101 QLegend *legend = m_chart->legend();
156 QLegend *legend = m_chart->legend();
102 legend->detachFromChart();
157 legend->detachFromChart();
103 legend->setGeometry(m_customView->rect());
158
104 m_customScene->addItem(legend);
159 m_chart->legend()->setBackgroundVisible(true);
160 m_chart->legend()->setBrush(QBrush(QColor(128,128,128,128)));
105 //![4]
161 //![4]
106
162
107 // This forces redraw
163 showLegendSpinbox();
108 QSize delta(1,1);
164 updateLegendLayout();
109 resize(size() + delta);
165 update();
110 resize(size() - delta);
111 }
166 }
112
167
113
168
114 void MainWidget::attachLegend()
169 void MainWidget::attachLegend()
115 {
170 {
116 // Remove legend from custom scene and put it back to chartview scene.
117 // Attach legend back to chart, so that layout works.
118
119 //![5]
171 //![5]
120 QLegend *legend = m_chart->legend();
172 QLegend *legend = m_chart->legend();
121
173 legend->attachToChart();
122 if (m_customScene->items().contains(legend)) {
174 m_chart->legend()->setBackgroundVisible(false);
123 m_customScene->removeItem(legend);
124 m_chartView->scene()->addItem(legend);
125 legend->attachToChart();
126 }
127 //![5]
175 //![5]
128
176
129 // This forces redraw
177 hideLegendSpinbox();
130 QSize delta(1,1);
178 update();
131 resize(size() + delta);
132 resize(size() - delta);
133 }
179 }
134
180
135 void MainWidget::addBarset()
181 void MainWidget::addBarset()
136 {
182 {
137 QBarSet *barSet = new QBarSet(QString("set ") + QString::number(m_series->barsetCount()));
183 QBarSet *barSet = new QBarSet(QString("set ") + QString::number(m_series->barsetCount()));
138 qreal delta = m_series->barsetCount() * 0.1;
184 qreal delta = m_series->barsetCount() * 0.1;
139 *barSet << QPointF(0.0 + delta, 1 + delta) << QPointF(1.0 + delta, 2 + delta) << QPointF(2.0 + delta, 3 + delta) << QPointF(3.0 + delta, 4 + delta);
185 *barSet << QPointF(0.0 + delta, 1 + delta) << QPointF(1.0 + delta, 2 + delta) << QPointF(2.0 + delta, 3 + delta) << QPointF(3.0 + delta, 4 + delta);
140 m_series->append(barSet);
186 m_series->append(barSet);
141 }
187 }
142
188
143 void MainWidget::removeBarset()
189 void MainWidget::removeBarset()
144 {
190 {
145 QList<QBarSet*> sets = m_series->barSets();
191 QList<QBarSet*> sets = m_series->barSets();
146 if (sets.count() > 0) {
192 if (sets.count() > 0) {
147 m_series->remove(sets.at(sets.count()-1));
193 m_series->remove(sets.at(sets.count()-1));
148 }
194 }
149 }
195 }
196
197 void MainWidget::setLegendLeft()
198 {
199 m_chart->legend()->setAlignment(Qt::AlignLeft);
200 }
201
202 void MainWidget::setLegendRight()
203 {
204 m_chart->legend()->setAlignment(Qt::AlignRight);
205 }
206
207 void MainWidget::setLegendTop()
208 {
209 m_chart->legend()->setAlignment(Qt::AlignTop);
210 }
211
212 void MainWidget::setLegendBottom()
213 {
214 m_chart->legend()->setAlignment(Qt::AlignBottom);
215 }
216
217 void MainWidget::updateLegendLayout()
218 {
219 m_chart->legend()->setGeometry(m_legendPosX->value()
220 ,m_legendPosY->value()
221 ,m_legendWidth->value()
222 ,m_legendHeight->value());
223 m_chart->legend()->update();
224 }
@@ -1,63 +1,77
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2012 Digia Plc
3 ** Copyright (C) 2012 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
6 **
7 ** This file is part of the Qt Commercial Charts Add-on.
7 ** This file is part of the Qt Commercial Charts Add-on.
8 **
8 **
9 ** $QT_BEGIN_LICENSE$
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Commercial licenses may use this file in
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
13 ** a written agreement between you and Digia.
14 **
14 **
15 ** If you have questions regarding the use of this file, please use
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
17 ** $QT_END_LICENSE$
18 **
18 **
19 ****************************************************************************/
19 ****************************************************************************/
20
20
21 #ifndef MAINWIDGET_H
21 #ifndef MAINWIDGET_H
22 #define MAINWIDGET_H
22 #define MAINWIDGET_H
23
23
24 #include "qchartglobal.h"
24 #include "qchartglobal.h"
25 #include "qchart.h"
25 #include "qchart.h"
26 #include "qchartview.h"
26 #include "qchartview.h"
27 #include <QWidget>
27 #include <QWidget>
28 #include <QGraphicsWidget>
28 #include <QGraphicsWidget>
29 #include <QGridLayout>
29 #include <QGridLayout>
30 #include <QGraphicsGridLayout>
30 #include <QGraphicsGridLayout>
31 #include <QDoubleSpinBox>
32 #include <QGroupBox>
31
33
32 QTCOMMERCIALCHART_USE_NAMESPACE
34 QTCOMMERCIALCHART_USE_NAMESPACE
33
35
34 class MainWidget : public QWidget
36 class MainWidget : public QWidget
35 {
37 {
36 Q_OBJECT
38 Q_OBJECT
37 public:
39 public:
38 explicit MainWidget(QWidget *parent = 0);
40 explicit MainWidget(QWidget *parent = 0);
39
40 void createSeries();
41 void createSeries();
41
42 void showLegendSpinbox();
43 void hideLegendSpinbox();
44
42 signals:
45 signals:
43
46
44 public slots:
47 public slots:
45 void detachLegend();
48 void detachLegend();
46 void attachLegend();
49 void attachLegend();
47 void addBarset();
50 void addBarset();
48 void removeBarset();
51 void removeBarset();
49
52
53 void setLegendLeft();
54 void setLegendRight();
55 void setLegendTop();
56 void setLegendBottom();
57
58 void updateLegendLayout();
59
50 private:
60 private:
51
61
52 QChart *m_chart;
62 QChart *m_chart;
53 QBarSeries *m_series;
63 QBarSeries *m_series;
54
64
55 QChartView *m_chartView;
65 QChartView *m_chartView;
56 QGridLayout *m_mainLayout;
66 QGridLayout *m_mainLayout;
57 QGridLayout *m_buttonLayout;
67 QGridLayout *m_buttonLayout;
58
68
59 QGraphicsView *m_customView;
69 // For detached layout
60 QGraphicsScene *m_customScene;
70 QGroupBox* m_legendSettings;
71 QDoubleSpinBox *m_legendPosX;
72 QDoubleSpinBox *m_legendPosY;
73 QDoubleSpinBox *m_legendWidth;
74 QDoubleSpinBox *m_legendHeight;
61 };
75 };
62
76
63 #endif // MAINWIDGET_H
77 #endif // MAINWIDGET_H
@@ -1,429 +1,429
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2012 Digia Plc
3 ** Copyright (C) 2012 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
6 **
7 ** This file is part of the Qt Commercial Charts Add-on.
7 ** This file is part of the Qt Commercial Charts Add-on.
8 **
8 **
9 ** $QT_BEGIN_LICENSE$
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Commercial licenses may use this file in
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
13 ** a written agreement between you and Digia.
14 **
14 **
15 ** If you have questions regarding the use of this file, please use
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
17 ** $QT_END_LICENSE$
18 **
18 **
19 ****************************************************************************/
19 ****************************************************************************/
20 #include "chartpresenter_p.h"
20 #include "chartpresenter_p.h"
21 #include "qchart.h"
21 #include "qchart.h"
22 #include "qchart_p.h"
22 #include "qchart_p.h"
23 #include "qaxis.h"
23 #include "qaxis.h"
24 #include "chartdataset_p.h"
24 #include "chartdataset_p.h"
25 #include "charttheme_p.h"
25 #include "charttheme_p.h"
26 #include "chartanimator_p.h"
26 #include "chartanimator_p.h"
27 #include "chartanimation_p.h"
27 #include "chartanimation_p.h"
28 #include "qabstractseries_p.h"
28 #include "qabstractseries_p.h"
29 #include "qareaseries.h"
29 #include "qareaseries.h"
30 #include "chartaxis_p.h"
30 #include "chartaxis_p.h"
31 #include "chartaxisx_p.h"
31 #include "chartaxisx_p.h"
32 #include "chartaxisy_p.h"
32 #include "chartaxisy_p.h"
33 #include "areachartitem_p.h"
33 #include "areachartitem_p.h"
34 #include "chartbackground_p.h"
34 #include "chartbackground_p.h"
35 #include <QTimer>
35 #include <QTimer>
36
36
37 QTCOMMERCIALCHART_BEGIN_NAMESPACE
37 QTCOMMERCIALCHART_BEGIN_NAMESPACE
38
38
39 ChartPresenter::ChartPresenter(QChart* chart,ChartDataSet* dataset):QObject(chart),
39 ChartPresenter::ChartPresenter(QChart* chart,ChartDataSet* dataset):QObject(chart),
40 m_chart(chart),
40 m_chart(chart),
41 m_animator(0),
41 m_animator(0),
42 m_dataset(dataset),
42 m_dataset(dataset),
43 m_chartTheme(0),
43 m_chartTheme(0),
44 m_chartRect(QRectF(QPoint(0,0),m_chart->size())),
44 m_chartRect(QRectF(QPoint(0,0),m_chart->size())),
45 m_options(QChart::NoAnimation),
45 m_options(QChart::NoAnimation),
46 m_minLeftMargin(0),
46 m_minLeftMargin(0),
47 m_minBottomMargin(0),
47 m_minBottomMargin(0),
48 m_state(ShowState),
48 m_state(ShowState),
49 m_backgroundItem(0),
49 m_backgroundItem(0),
50 m_titleItem(0),
50 m_titleItem(0),
51 m_marginBig(60),
51 m_marginBig(60),
52 m_marginSmall(20),
52 m_marginSmall(20),
53 m_marginTiny(10),
53 m_marginTiny(10),
54 m_chartMargins(QRect(m_marginBig,m_marginBig,0,0))
54 m_chartMargins(QRect(m_marginBig,m_marginBig,0,0))
55 {
55 {
56
56
57 }
57 }
58
58
59 ChartPresenter::~ChartPresenter()
59 ChartPresenter::~ChartPresenter()
60 {
60 {
61 delete m_chartTheme;
61 delete m_chartTheme;
62 }
62 }
63
63
64 void ChartPresenter::setGeometry(const QRectF& rect)
64 void ChartPresenter::setGeometry(const QRectF& rect)
65 {
65 {
66 m_rect = rect;
66 m_rect = rect;
67 Q_ASSERT(m_rect.isValid());
67 Q_ASSERT(m_rect.isValid());
68 updateLayout();
68 updateLayout();
69 }
69 }
70
70
71 void ChartPresenter::setMinimumMarginWidth(ChartAxis* axis, qreal width)
71 void ChartPresenter::setMinimumMarginWidth(ChartAxis* axis, qreal width)
72 {
72 {
73 switch(axis->axisType()){
73 switch(axis->axisType()){
74 case ChartAxis::X_AXIS:
74 case ChartAxis::X_AXIS:
75 {
75 {
76 if(width>m_chartRect.width()+ m_chartMargins.left()) {
76 if(width>m_chartRect.width()+ m_chartMargins.left()) {
77 m_minLeftMargin= width - m_chartRect.width();
77 m_minLeftMargin= width - m_chartRect.width();
78 updateLayout();
78 updateLayout();
79 }
79 }
80 break;
80 break;
81 }
81 }
82 case ChartAxis::Y_AXIS:
82 case ChartAxis::Y_AXIS:
83 {
83 {
84
84
85 if(m_minLeftMargin!=width){
85 if(m_minLeftMargin!=width){
86 m_minLeftMargin= width;
86 m_minLeftMargin= width;
87 updateLayout();
87 updateLayout();
88 }
88 }
89 break;
89 break;
90 }
90 }
91
91
92 }
92 }
93 }
93 }
94
94
95 void ChartPresenter::setMinimumMarginHeight(ChartAxis* axis, qreal height)
95 void ChartPresenter::setMinimumMarginHeight(ChartAxis* axis, qreal height)
96 {
96 {
97 switch(axis->axisType()){
97 switch(axis->axisType()){
98 case ChartAxis::X_AXIS:
98 case ChartAxis::X_AXIS:
99 {
99 {
100 if(m_minBottomMargin!=height) {
100 if(m_minBottomMargin!=height) {
101 m_minBottomMargin= height;
101 m_minBottomMargin= height;
102 updateLayout();
102 updateLayout();
103 }
103 }
104 break;
104 break;
105 }
105 }
106 case ChartAxis::Y_AXIS:
106 case ChartAxis::Y_AXIS:
107 {
107 {
108
108
109 if(height>m_chartMargins.bottom()+m_chartRect.height()){
109 if(height>m_chartMargins.bottom()+m_chartRect.height()){
110 m_minBottomMargin= height - m_chartRect.height();
110 m_minBottomMargin= height - m_chartRect.height();
111 updateLayout();
111 updateLayout();
112 }
112 }
113 break;
113 break;
114 }
114 }
115
115
116 }
116 }
117 }
117 }
118
118
119 void ChartPresenter::handleAxisAdded(QAxis* axis,Domain* domain)
119 void ChartPresenter::handleAxisAdded(QAxis* axis,Domain* domain)
120 {
120 {
121 ChartAxis* item;
121 ChartAxis* item;
122
122
123 if(axis == m_dataset->axisX()){
123 if(axis == m_dataset->axisX()){
124 item = new ChartAxisX(axis,this);
124 item = new ChartAxisX(axis,this);
125 }else{
125 }else{
126 item = new ChartAxisY(axis,this);
126 item = new ChartAxisY(axis,this);
127 }
127 }
128
128
129 if(m_options.testFlag(QChart::GridAxisAnimations)){
129 if(m_options.testFlag(QChart::GridAxisAnimations)){
130 item->setAnimator(m_animator);
130 item->setAnimator(m_animator);
131 item->setAnimation(new AxisAnimation(item));
131 item->setAnimation(new AxisAnimation(item));
132 }
132 }
133
133
134 if(axis==m_dataset->axisX()){
134 if(axis==m_dataset->axisX()){
135 m_chartTheme->decorate(axis,true);
135 m_chartTheme->decorate(axis,true);
136 QObject::connect(domain,SIGNAL(rangeXChanged(qreal,qreal,int)),item,SLOT(handleRangeChanged(qreal,qreal,int)));
136 QObject::connect(domain,SIGNAL(rangeXChanged(qreal,qreal,int)),item,SLOT(handleRangeChanged(qreal,qreal,int)));
137 //initialize
137 //initialize
138 item->handleRangeChanged(domain->minX(),domain->maxX(),domain->tickXCount());
138 item->handleRangeChanged(domain->minX(),domain->maxX(),domain->tickXCount());
139
139
140 }
140 }
141 else{
141 else{
142 m_chartTheme->decorate(axis,false);
142 m_chartTheme->decorate(axis,false);
143 QObject::connect(domain,SIGNAL(rangeYChanged(qreal,qreal,int)),item,SLOT(handleRangeChanged(qreal,qreal,int)));
143 QObject::connect(domain,SIGNAL(rangeYChanged(qreal,qreal,int)),item,SLOT(handleRangeChanged(qreal,qreal,int)));
144 //initialize
144 //initialize
145 item->handleRangeChanged(domain->minY(),domain->maxY(),domain->tickYCount());
145 item->handleRangeChanged(domain->minY(),domain->maxY(),domain->tickYCount());
146 }
146 }
147
147
148 QObject::connect(this,SIGNAL(geometryChanged(QRectF)),item,SLOT(handleGeometryChanged(QRectF)));
148 QObject::connect(this,SIGNAL(geometryChanged(QRectF)),item,SLOT(handleGeometryChanged(QRectF)));
149 //initialize
149 //initialize
150 if(m_chartRect.isValid()) item->handleGeometryChanged(m_chartRect);
150 if(m_chartRect.isValid()) item->handleGeometryChanged(m_chartRect);
151 m_axisItems.insert(axis, item);
151 m_axisItems.insert(axis, item);
152 }
152 }
153
153
154 void ChartPresenter::handleAxisRemoved(QAxis* axis)
154 void ChartPresenter::handleAxisRemoved(QAxis* axis)
155 {
155 {
156 ChartAxis* item = m_axisItems.take(axis);
156 ChartAxis* item = m_axisItems.take(axis);
157 Q_ASSERT(item);
157 Q_ASSERT(item);
158 if(m_animator) m_animator->removeAnimation(item);
158 if(m_animator) m_animator->removeAnimation(item);
159 delete item;
159 delete item;
160 }
160 }
161
161
162
162
163 void ChartPresenter::handleSeriesAdded(QAbstractSeries* series,Domain* domain)
163 void ChartPresenter::handleSeriesAdded(QAbstractSeries* series,Domain* domain)
164 {
164 {
165 Chart *item = series->d_ptr->createGraphics(this);
165 Chart *item = series->d_ptr->createGraphics(this);
166 Q_ASSERT(item);
166 Q_ASSERT(item);
167 QObject::connect(this,SIGNAL(geometryChanged(QRectF)),item,SLOT(handleGeometryChanged(QRectF)));
167 QObject::connect(this,SIGNAL(geometryChanged(QRectF)),item,SLOT(handleGeometryChanged(QRectF)));
168 QObject::connect(domain,SIGNAL(domainChanged(qreal,qreal,qreal,qreal)),item,SLOT(handleDomainChanged(qreal,qreal,qreal,qreal)));
168 QObject::connect(domain,SIGNAL(domainChanged(qreal,qreal,qreal,qreal)),item,SLOT(handleDomainChanged(qreal,qreal,qreal,qreal)));
169 //initialize
169 //initialize
170 item->handleDomainChanged(domain->minX(),domain->maxX(),domain->minY(),domain->maxY());
170 item->handleDomainChanged(domain->minX(),domain->maxX(),domain->minY(),domain->maxY());
171 if(m_chartRect.isValid()) item->handleGeometryChanged(m_chartRect);
171 if(m_chartRect.isValid()) item->handleGeometryChanged(m_chartRect);
172 m_chartItems.insert(series,item);
172 m_chartItems.insert(series,item);
173 }
173 }
174
174
175 void ChartPresenter::handleSeriesRemoved(QAbstractSeries* series)
175 void ChartPresenter::handleSeriesRemoved(QAbstractSeries* series)
176 {
176 {
177 Chart* item = m_chartItems.take(series);
177 Chart* item = m_chartItems.take(series);
178 Q_ASSERT(item);
178 Q_ASSERT(item);
179 if(m_animator) {
179 if(m_animator) {
180 //small hack to handle area animations
180 //small hack to handle area animations
181 if(series->type() == QAbstractSeries::SeriesTypeArea){
181 if(series->type() == QAbstractSeries::SeriesTypeArea){
182 QAreaSeries* areaSeries = static_cast<QAreaSeries*>(series);
182 QAreaSeries* areaSeries = static_cast<QAreaSeries*>(series);
183 AreaChartItem* area = static_cast<AreaChartItem*>(item);
183 AreaChartItem* area = static_cast<AreaChartItem*>(item);
184 m_animator->removeAnimation(area->upperLineItem());
184 m_animator->removeAnimation(area->upperLineItem());
185 if(areaSeries->lowerSeries()) m_animator->removeAnimation(area->lowerLineItem());
185 if(areaSeries->lowerSeries()) m_animator->removeAnimation(area->lowerLineItem());
186 }else
186 }else
187 m_animator->removeAnimation(item);
187 m_animator->removeAnimation(item);
188 }
188 }
189 delete item;
189 delete item;
190 }
190 }
191
191
192 void ChartPresenter::setTheme(QChart::ChartTheme theme,bool force)
192 void ChartPresenter::setTheme(QChart::ChartTheme theme,bool force)
193 {
193 {
194 if(m_chartTheme && m_chartTheme->id() == theme) return;
194 if(m_chartTheme && m_chartTheme->id() == theme) return;
195 delete m_chartTheme;
195 delete m_chartTheme;
196 m_chartTheme = ChartTheme::createTheme(theme);
196 m_chartTheme = ChartTheme::createTheme(theme);
197 m_chartTheme->setForced(force);
197 m_chartTheme->setForced(force);
198 m_chartTheme->decorate(m_chart);
198 m_chartTheme->decorate(m_chart);
199 m_chartTheme->decorate(m_chart->legend());
199 m_chartTheme->decorate(m_chart->legend());
200 resetAllElements();
200 resetAllElements();
201
201
202 // We do not want "force" to stay on.
202 // We do not want "force" to stay on.
203 // Bar/pie are calling decorate when adding/removing slices/bars which means
203 // Bar/pie are calling decorate when adding/removing slices/bars which means
204 // that to preserve users colors "force" must not be on.
204 // that to preserve users colors "force" must not be on.
205 m_chartTheme->setForced(false);
205 m_chartTheme->setForced(false);
206 }
206 }
207
207
208 QChart::ChartTheme ChartPresenter::theme()
208 QChart::ChartTheme ChartPresenter::theme()
209 {
209 {
210 return m_chartTheme->id();
210 return m_chartTheme->id();
211 }
211 }
212
212
213 void ChartPresenter::setAnimationOptions(QChart::AnimationOptions options)
213 void ChartPresenter::setAnimationOptions(QChart::AnimationOptions options)
214 {
214 {
215 if(m_options!=options) {
215 if(m_options!=options) {
216
216
217 m_options=options;
217 m_options=options;
218
218
219 if(m_options!=QChart::NoAnimation && !m_animator) {
219 if(m_options!=QChart::NoAnimation && !m_animator) {
220 m_animator= new ChartAnimator(this);
220 m_animator= new ChartAnimator(this);
221 }
221 }
222 resetAllElements();
222 resetAllElements();
223 }
223 }
224
224
225 }
225 }
226
226
227 void ChartPresenter::resetAllElements()
227 void ChartPresenter::resetAllElements()
228 {
228 {
229 QList<QAxis *> axisList = m_axisItems.uniqueKeys();
229 QList<QAxis *> axisList = m_axisItems.uniqueKeys();
230 QList<QAbstractSeries *> seriesList = m_chartItems.uniqueKeys();
230 QList<QAbstractSeries *> seriesList = m_chartItems.uniqueKeys();
231
231
232 foreach(QAxis *axis, axisList) {
232 foreach(QAxis *axis, axisList) {
233 handleAxisRemoved(axis);
233 handleAxisRemoved(axis);
234 handleAxisAdded(axis,m_dataset->domain(axis));
234 handleAxisAdded(axis,m_dataset->domain(axis));
235 }
235 }
236 foreach(QAbstractSeries *series, seriesList) {
236 foreach(QAbstractSeries *series, seriesList) {
237 handleSeriesRemoved(series);
237 handleSeriesRemoved(series);
238 handleSeriesAdded(series,m_dataset->domain(series));
238 handleSeriesAdded(series,m_dataset->domain(series));
239 // m_dataset->removeSeries(series);
239 // m_dataset->removeSeries(series);
240 // m_dataset->addSeries(series);
240 // m_dataset->addSeries(series);
241 }
241 }
242 }
242 }
243
243
244 void ChartPresenter::zoomIn(qreal factor)
244 void ChartPresenter::zoomIn(qreal factor)
245 {
245 {
246 QRectF rect = chartGeometry();
246 QRectF rect = chartGeometry();
247 rect.setWidth(rect.width()/factor);
247 rect.setWidth(rect.width()/factor);
248 rect.setHeight(rect.height()/factor);
248 rect.setHeight(rect.height()/factor);
249 rect.moveCenter(chartGeometry().center());
249 rect.moveCenter(chartGeometry().center());
250 zoomIn(rect);
250 zoomIn(rect);
251 }
251 }
252
252
253 void ChartPresenter::zoomIn(const QRectF& rect)
253 void ChartPresenter::zoomIn(const QRectF& rect)
254 {
254 {
255 QRectF r = rect.normalized();
255 QRectF r = rect.normalized();
256 r.translate(-m_chartMargins.topLeft());
256 r.translate(-m_chartMargins.topLeft());
257 if (!r.isValid())
257 if (!r.isValid())
258 return;
258 return;
259
259
260 m_state = ZoomInState;
260 m_state = ZoomInState;
261 m_statePoint = QPointF(r.center().x()/chartGeometry().width(),r.center().y()/chartGeometry().height());
261 m_statePoint = QPointF(r.center().x()/chartGeometry().width(),r.center().y()/chartGeometry().height());
262 m_dataset->zoomInDomain(r,chartGeometry().size());
262 m_dataset->zoomInDomain(r,chartGeometry().size());
263 m_state = ShowState;
263 m_state = ShowState;
264 }
264 }
265
265
266 void ChartPresenter::zoomOut(qreal factor)
266 void ChartPresenter::zoomOut(qreal factor)
267 {
267 {
268 m_state = ZoomOutState;
268 m_state = ZoomOutState;
269
269
270 QRectF chartRect;
270 QRectF chartRect;
271 chartRect.setSize(chartGeometry().size());
271 chartRect.setSize(chartGeometry().size());
272
272
273 QRectF rect;
273 QRectF rect;
274 rect.setSize(chartRect.size()/factor);
274 rect.setSize(chartRect.size()/factor);
275 rect.moveCenter(chartRect.center());
275 rect.moveCenter(chartRect.center());
276 if (!rect.isValid())
276 if (!rect.isValid())
277 return;
277 return;
278 m_statePoint = QPointF(rect.center().x()/chartGeometry().width(),rect.center().y()/chartGeometry().height());
278 m_statePoint = QPointF(rect.center().x()/chartGeometry().width(),rect.center().y()/chartGeometry().height());
279 m_dataset->zoomOutDomain(rect, chartRect.size());
279 m_dataset->zoomOutDomain(rect, chartRect.size());
280 m_state = ShowState;
280 m_state = ShowState;
281 }
281 }
282
282
283 void ChartPresenter::scroll(qreal dx,qreal dy)
283 void ChartPresenter::scroll(qreal dx,qreal dy)
284 {
284 {
285 if(dx<0) m_state=ScrollLeftState;
285 if(dx<0) m_state=ScrollLeftState;
286 if(dx>0) m_state=ScrollRightState;
286 if(dx>0) m_state=ScrollRightState;
287 if(dy<0) m_state=ScrollUpState;
287 if(dy<0) m_state=ScrollUpState;
288 if(dy>0) m_state=ScrollDownState;
288 if(dy>0) m_state=ScrollDownState;
289
289
290 m_dataset->scrollDomain(dx,dy,chartGeometry().size());
290 m_dataset->scrollDomain(dx,dy,chartGeometry().size());
291 m_state = ShowState;
291 m_state = ShowState;
292 }
292 }
293
293
294 QChart::AnimationOptions ChartPresenter::animationOptions() const
294 QChart::AnimationOptions ChartPresenter::animationOptions() const
295 {
295 {
296 return m_options;
296 return m_options;
297 }
297 }
298
298
299 void ChartPresenter::updateLayout()
299 void ChartPresenter::updateLayout()
300 {
300 {
301 if (!m_rect.isValid()) return;
301 if (!m_rect.isValid()) return;
302
302
303 // recalculate title size
303 // recalculate title size
304
304
305 QSize titleSize;
305 QSize titleSize;
306 int titlePadding=0;
306 int titlePadding=0;
307
307
308 if (m_titleItem) {
308 if (m_titleItem) {
309 titleSize= m_titleItem->boundingRect().size().toSize();
309 titleSize= m_titleItem->boundingRect().size().toSize();
310 }
310 }
311
311
312 //defaults
312 //defaults
313 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));
313 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));
314 titlePadding = m_chartMargins.top()/2;
314 titlePadding = m_chartMargins.top()/2;
315
315
316 QLegend* legend = m_chart->d_ptr->m_legend;
316 QLegend* legend = m_chart->d_ptr->m_legend;
317
317
318 // recalculate legend position
318 // recalculate legend position
319 if (legend != 0 && legend->isAttachedToChart() && legend->isEnabled()) {
319 if (legend != 0 && legend->isAttachedToChart() && legend->isEnabled()) {
320
320
321 QRect legendRect;
322
323 // Reserve some space for legend
321 // Reserve some space for legend
324 switch (legend->alignment()) {
322 switch (legend->alignment()) {
325
323
326 case Qt::AlignTop: {
324 case Qt::AlignTop: {
327 int ledgendSize = legend->minHeight();
325 int ledgendSize = legend->minHeight();
328 int topPadding = 2*m_marginTiny + titleSize.height() + ledgendSize + m_marginTiny;
326 int topPadding = 2*m_marginTiny + titleSize.height() + ledgendSize + m_marginTiny;
329 m_chartMargins = QRect(QPoint(m_chartMargins.left(),topPadding),QPoint(m_chartMargins.right(),m_chartMargins.bottom()));
327 m_chartMargins = QRect(QPoint(m_chartMargins.left(),topPadding),QPoint(m_chartMargins.right(),m_chartMargins.bottom()));
330 m_legendMargins = QRect(QPoint(m_chartMargins.left(),topPadding - (ledgendSize + m_marginTiny)),QPoint(m_chartMargins.right(),m_rect.height()-topPadding + m_marginTiny));
328 m_legendMargins = QRect(QPoint(m_chartMargins.left(),topPadding - (ledgendSize + m_marginTiny)),QPoint(m_chartMargins.right(),m_rect.height()-topPadding + m_marginTiny));
331 titlePadding = m_marginTiny + m_marginTiny;
329 titlePadding = m_marginTiny + m_marginTiny;
332 break;
330 break;
333 }
331 }
334 case Qt::AlignBottom: {
332 case Qt::AlignBottom: {
335 int ledgendSize = legend->minHeight();
333 int ledgendSize = legend->minHeight();
336 int bottomPadding = m_marginTiny + m_marginSmall + ledgendSize + m_marginTiny + m_minBottomMargin;
334 int bottomPadding = m_marginTiny + m_marginSmall + ledgendSize + m_marginTiny + m_minBottomMargin;
337 m_chartMargins = QRect(QPoint(m_chartMargins.left(),m_chartMargins.top()),QPoint(m_chartMargins.right(),bottomPadding));
335 m_chartMargins = QRect(QPoint(m_chartMargins.left(),m_chartMargins.top()),QPoint(m_chartMargins.right(),bottomPadding));
338 m_legendMargins = QRect(QPoint(m_chartMargins.left(),m_rect.height()-bottomPadding + m_marginTiny + m_minBottomMargin),QPoint(m_chartMargins.right(),m_marginTiny + m_marginSmall));
336 m_legendMargins = QRect(QPoint(m_chartMargins.left(),m_rect.height()-bottomPadding + m_marginTiny + m_minBottomMargin),QPoint(m_chartMargins.right(),m_marginTiny + m_marginSmall));
339 titlePadding = m_chartMargins.top()/2;
337 titlePadding = m_chartMargins.top()/2;
340 break;
338 break;
341 }
339 }
342 case Qt::AlignLeft: {
340 case Qt::AlignLeft: {
343 int ledgendSize = legend->minWidth();
341 int ledgendSize = legend->minWidth();
344 int leftPadding = m_marginTiny + m_marginSmall + ledgendSize + m_marginTiny + m_minLeftMargin;
342 int leftPadding = m_marginTiny + m_marginSmall + ledgendSize + m_marginTiny + m_minLeftMargin;
345 m_chartMargins = QRect(QPoint(leftPadding,m_chartMargins.top()),QPoint(m_chartMargins.right(),m_chartMargins.bottom()));
343 m_chartMargins = QRect(QPoint(leftPadding,m_chartMargins.top()),QPoint(m_chartMargins.right(),m_chartMargins.bottom()));
346 m_legendMargins = QRect(QPoint(m_marginTiny + m_marginSmall,m_chartMargins.top()),QPoint(m_rect.width()-leftPadding + m_marginTiny + m_minLeftMargin,m_chartMargins.bottom()));
344 m_legendMargins = QRect(QPoint(m_marginTiny + m_marginSmall,m_chartMargins.top()),QPoint(m_rect.width()-leftPadding + m_marginTiny + m_minLeftMargin,m_chartMargins.bottom()));
347 titlePadding = m_chartMargins.top()/2;
345 titlePadding = m_chartMargins.top()/2;
348 break;
346 break;
349 }
347 }
350 case Qt::AlignRight: {
348 case Qt::AlignRight: {
351 int ledgendSize = legend->minWidth();
349 int ledgendSize = legend->minWidth();
352 int rightPadding = m_marginTiny + m_marginSmall + ledgendSize + m_marginTiny;
350 int rightPadding = m_marginTiny + m_marginSmall + ledgendSize + m_marginTiny;
353 m_chartMargins = QRect(QPoint(m_chartMargins.left(),m_chartMargins.top()),QPoint(rightPadding,m_chartMargins.bottom()));
351 m_chartMargins = QRect(QPoint(m_chartMargins.left(),m_chartMargins.top()),QPoint(rightPadding,m_chartMargins.bottom()));
354 m_legendMargins = QRect(QPoint(m_rect.width()- rightPadding+ m_marginTiny ,m_chartMargins.top()),QPoint(m_marginTiny + m_marginSmall,m_chartMargins.bottom()));
352 m_legendMargins = QRect(QPoint(m_rect.width()- rightPadding+ m_marginTiny ,m_chartMargins.top()),QPoint(m_marginTiny + m_marginSmall,m_chartMargins.bottom()));
355 titlePadding = m_chartMargins.top()/2;
353 titlePadding = m_chartMargins.top()/2;
356 break;
354 break;
357 }
355 }
358 default: {
356 default: {
359 break;
357 break;
360 }
358 }
361 }
359 }
362 }
360 }
363
361
364 if(m_rect.width()<2*(m_chartMargins.top()+m_chartMargins.bottom()) || m_rect.height()< 2*(m_chartMargins.top() + m_chartMargins.bottom()))
362 if(m_rect.width()<2*(m_chartMargins.top()+m_chartMargins.bottom()) || m_rect.height()< 2*(m_chartMargins.top() + m_chartMargins.bottom()))
365 {
363 {
366 m_chart->setMinimumSize(2*(m_chartMargins.top()+m_chartMargins.bottom()),2*(m_chartMargins.top() + m_chartMargins.bottom()));
364 m_chart->setMinimumSize(2*(m_chartMargins.top()+m_chartMargins.bottom()),2*(m_chartMargins.top() + m_chartMargins.bottom()));
367 return;
365 return;
368 }
366 }
369
367
370
368
371 // recalculate title position
369 // recalculate title position
372 if (m_titleItem) {
370 if (m_titleItem) {
373 QPointF center = m_rect.center() -m_titleItem->boundingRect().center();
371 QPointF center = m_rect.center() -m_titleItem->boundingRect().center();
374 m_titleItem->setPos(center.x(),titlePadding);
372 m_titleItem->setPos(center.x(),titlePadding);
375 }
373 }
376
374
377 //recalculate background gradient
375 //recalculate background gradient
378 if (m_backgroundItem) {
376 if (m_backgroundItem) {
379 m_backgroundItem->setRect(m_rect.adjusted(m_marginTiny,m_marginTiny, -m_marginTiny, -m_marginTiny));
377 m_backgroundItem->setRect(m_rect.adjusted(m_marginTiny,m_marginTiny, -m_marginTiny, -m_marginTiny));
380 }
378 }
381
379
382
380
383 QRectF chartRect = m_rect.adjusted(m_chartMargins.left(),m_chartMargins.top(),-m_chartMargins.right(),-m_chartMargins.bottom());
381 QRectF chartRect = m_rect.adjusted(m_chartMargins.left(),m_chartMargins.top(),-m_chartMargins.right(),-m_chartMargins.bottom());
384
382
385 legend->setGeometry(m_rect.adjusted(m_legendMargins.left(),m_legendMargins.top(),-m_legendMargins.right(),-m_legendMargins.bottom()));
383 if (legend != 0 && legend->isAttachedToChart() && legend->isEnabled()) {
384 legend->setGeometry(m_rect.adjusted(m_legendMargins.left(),m_legendMargins.top(),-m_legendMargins.right(),-m_legendMargins.bottom()));
385 }
386
386
387 if(m_chartRect!=chartRect && chartRect.isValid()){
387 if(m_chartRect!=chartRect && chartRect.isValid()){
388 m_chartRect=chartRect;
388 m_chartRect=chartRect;
389 emit geometryChanged(m_chartRect);
389 emit geometryChanged(m_chartRect);
390 }
390 }
391
391
392 }
392 }
393
393
394 void ChartPresenter::createChartBackgroundItem()
394 void ChartPresenter::createChartBackgroundItem()
395 {
395 {
396 if (!m_backgroundItem) {
396 if (!m_backgroundItem) {
397 m_backgroundItem = new ChartBackground(rootItem());
397 m_backgroundItem = new ChartBackground(rootItem());
398 m_backgroundItem->setPen(Qt::NoPen);
398 m_backgroundItem->setPen(Qt::NoPen);
399 m_backgroundItem->setZValue(ChartPresenter::BackgroundZValue);
399 m_backgroundItem->setZValue(ChartPresenter::BackgroundZValue);
400 }
400 }
401 }
401 }
402
402
403 void ChartPresenter::createChartTitleItem()
403 void ChartPresenter::createChartTitleItem()
404 {
404 {
405 if (!m_titleItem) {
405 if (!m_titleItem) {
406 m_titleItem = new QGraphicsSimpleTextItem(rootItem());
406 m_titleItem = new QGraphicsSimpleTextItem(rootItem());
407 m_titleItem->setZValue(ChartPresenter::BackgroundZValue);
407 m_titleItem->setZValue(ChartPresenter::BackgroundZValue);
408 }
408 }
409 }
409 }
410
410
411 void ChartPresenter::handleAnimationFinished()
411 void ChartPresenter::handleAnimationFinished()
412 {
412 {
413 m_animations.removeAll(qobject_cast<ChartAnimation*>(sender()));
413 m_animations.removeAll(qobject_cast<ChartAnimation*>(sender()));
414 if(m_animations.empty()) emit animationsFinished();
414 if(m_animations.empty()) emit animationsFinished();
415 }
415 }
416
416
417 void ChartPresenter::startAnimation(ChartAnimation* animation)
417 void ChartPresenter::startAnimation(ChartAnimation* animation)
418 {
418 {
419 if (animation->state() != QAbstractAnimation::Stopped) animation->stop();
419 if (animation->state() != QAbstractAnimation::Stopped) animation->stop();
420 QObject::connect(animation, SIGNAL(finished()),this,SLOT(handleAnimationFinished()),Qt::UniqueConnection);
420 QObject::connect(animation, SIGNAL(finished()),this,SLOT(handleAnimationFinished()),Qt::UniqueConnection);
421 if(!m_animations.isEmpty()){
421 if(!m_animations.isEmpty()){
422 m_animations.append(animation);
422 m_animations.append(animation);
423 }
423 }
424 QTimer::singleShot(0, animation, SLOT(start()));
424 QTimer::singleShot(0, animation, SLOT(start()));
425 }
425 }
426
426
427 #include "moc_chartpresenter_p.cpp"
427 #include "moc_chartpresenter_p.cpp"
428
428
429 QTCOMMERCIALCHART_END_NAMESPACE
429 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,479 +1,621
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2012 Digia Plc
3 ** Copyright (C) 2012 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
6 **
7 ** This file is part of the Qt Commercial Charts Add-on.
7 ** This file is part of the Qt Commercial Charts Add-on.
8 **
8 **
9 ** $QT_BEGIN_LICENSE$
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Commercial licenses may use this file in
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
13 ** a written agreement between you and Digia.
14 **
14 **
15 ** If you have questions regarding the use of this file, please use
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
17 ** $QT_END_LICENSE$
18 **
18 **
19 ****************************************************************************/
19 ****************************************************************************/
20
20
21 #include "qlegend.h"
21 #include "qlegend.h"
22 #include "qlegend_p.h"
22 #include "qlegend_p.h"
23 #include "qabstractseries.h"
23 #include "qabstractseries.h"
24 #include "qabstractseries_p.h"
24 #include "qabstractseries_p.h"
25 #include "qchart_p.h"
25 #include "qchart_p.h"
26
26
27 #include "legendmarker_p.h"
27 #include "legendmarker_p.h"
28 #include "qxyseries.h"
28 #include "qxyseries.h"
29 #include "qlineseries.h"
29 #include "qlineseries.h"
30 #include "qareaseries.h"
30 #include "qareaseries.h"
31 #include "qscatterseries.h"
31 #include "qscatterseries.h"
32 #include "qsplineseries.h"
32 #include "qsplineseries.h"
33 #include "qbarseries.h"
33 #include "qbarseries.h"
34 #include "qstackedbarseries.h"
34 #include "qstackedbarseries.h"
35 #include "qpercentbarseries.h"
35 #include "qpercentbarseries.h"
36 #include "qbarset.h"
36 #include "qbarset.h"
37 #include "qpieseries.h"
37 #include "qpieseries.h"
38 #include "qpieseries_p.h"
38 #include "qpieseries_p.h"
39 #include "qpieslice.h"
39 #include "qpieslice.h"
40 #include "chartpresenter_p.h"
40 #include "chartpresenter_p.h"
41 #include <QPainter>
41 #include <QPainter>
42 #include <QPen>
42 #include <QPen>
43 #include <QTimer>
43 #include <QTimer>
44
44
45 #include <QGraphicsSceneEvent>
45 #include <QGraphicsSceneEvent>
46
46
47 QTCOMMERCIALCHART_BEGIN_NAMESPACE
47 QTCOMMERCIALCHART_BEGIN_NAMESPACE
48
48
49 /*!
49 /*!
50 \class QLegend
50 \class QLegend
51 \brief part of QtCommercial chart API.
51 \brief part of QtCommercial chart API.
52 \mainclass
52 \mainclass
53
53
54 QLegend is a graphical object, whics displays legend of the chart. Legend state is updated by QChart, when
54 QLegend is a graphical object, whics displays legend of the chart. Legend state is updated by QChart, when
55 series have been changed. By default, legend is drawn by QChart, but user can set a new parent to legend and
55 series have been changed. By default, legend is drawn by QChart, but user can set a new parent to legend and
56 handle the drawing manually.
56 handle the drawing manually.
57 User isn't supposed to create or delete legend objects, but can reference it via QChart class.
57 User isn't supposed to create or delete legend objects, but can reference it via QChart class.
58
58
59 \image examples_percentbarchart_legend.png
59 \image examples_percentbarchart_legend.png
60
60
61 \sa QChart
61 \sa QChart
62 */
62 */
63
63
64 /*!
64 /*!
65 \fn void QLegend::alignmentChanged()
65 \fn void QLegend::alignmentChanged()
66 Emitted when the alignment of the legend changes.
66 Emitted when the alignment of the legend changes.
67 */
67 */
68
68
69 /*!
69 /*!
70 \fn qreal QLegend::minWidth() const
70 \fn qreal QLegend::minWidth() const
71 Returns minimum width of the legend
71 Returns minimum width of the legend
72 */
72 */
73
73
74 /*!
74 /*!
75 \fn qreal QLegend::minHeight() const
75 \fn qreal QLegend::minHeight() const
76 Returns minimum height of the legend
76 Returns minimum height of the legend
77 */
77 */
78
78
79 /*!
79 /*!
80 Constructs the legend object and sets the parent to \a parent
80 Constructs the legend object and sets the parent to \a parent
81 */
81 */
82
82
83 QLegend::QLegend(QChart *chart):QGraphicsWidget(chart),
83 QLegend::QLegend(QChart *chart):QGraphicsWidget(chart),
84 d_ptr(new QLegendPrivate(chart->d_ptr->m_presenter,chart,this))
84 d_ptr(new QLegendPrivate(chart->d_ptr->m_presenter,chart,this))
85 {
85 {
86 setZValue(ChartPresenter::LegendZValue);
86 setZValue(ChartPresenter::LegendZValue);
87 setFlags(QGraphicsItem::ItemClipsChildrenToShape);
87 setFlags(QGraphicsItem::ItemClipsChildrenToShape);
88 QObject::connect(chart->d_ptr->m_dataset,SIGNAL(seriesAdded(QAbstractSeries*,Domain*)),d_ptr.data(),SLOT(handleSeriesAdded(QAbstractSeries*,Domain*)));
88 QObject::connect(chart->d_ptr->m_dataset,SIGNAL(seriesAdded(QAbstractSeries*,Domain*)),d_ptr.data(),SLOT(handleSeriesAdded(QAbstractSeries*,Domain*)));
89 QObject::connect(chart->d_ptr->m_dataset,SIGNAL(seriesRemoved(QAbstractSeries*)),d_ptr.data(),SLOT(handleSeriesRemoved(QAbstractSeries*)));
89 QObject::connect(chart->d_ptr->m_dataset,SIGNAL(seriesRemoved(QAbstractSeries*)),d_ptr.data(),SLOT(handleSeriesRemoved(QAbstractSeries*)));
90 QObject::connect(chart->d_ptr->m_dataset,SIGNAL(seriesUpdated(QAbstractSeries*)),d_ptr.data(),SLOT(handleSeriesUpdated(QAbstractSeries*)));
90 QObject::connect(chart->d_ptr->m_dataset,SIGNAL(seriesUpdated(QAbstractSeries*)),d_ptr.data(),SLOT(handleSeriesUpdated(QAbstractSeries*)));
91 }
91 }
92
92
93 /*!
93 /*!
94 Destroys the legend object. Legend is always owned by a QChart, so an application should never call this.
94 Destroys the legend object. Legend is always owned by a QChart, so an application should never call this.
95 */
95 */
96 QLegend::~QLegend()
96 QLegend::~QLegend()
97 {
97 {
98 }
98 }
99
99
100 /*!
100 /*!
101 Paints the legend to given \a painter. Paremeters \a option and \a widget arent used.
101 Paints the legend to given \a painter. Paremeters \a option and \a widget arent used.
102 */
102 */
103
103
104 void QLegend::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
104 void QLegend::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
105 {
105 {
106 Q_UNUSED(option)
106 Q_UNUSED(option)
107 Q_UNUSED(widget)
107 Q_UNUSED(widget)
108 if(!d_ptr->m_backgroundVisible) return;
108 if(!d_ptr->m_backgroundVisible) return;
109
109
110 painter->setOpacity(opacity());
110 painter->setOpacity(opacity());
111 painter->setPen(d_ptr->m_pen);
111 painter->setPen(d_ptr->m_pen);
112 painter->setBrush(d_ptr->m_brush);
112 painter->setBrush(d_ptr->m_brush);
113 painter->drawRect(boundingRect());
113 painter->drawRect(boundingRect());
114 }
114 }
115
115
116 /*!
116 /*!
117 Bounding rect of legend.
117 Bounding rect of legend.
118 */
118 */
119
119
120 QRectF QLegend::boundingRect() const
120 QRectF QLegend::boundingRect() const
121 {
121 {
122 return d_ptr->m_rect;
122 return d_ptr->m_rect;
123 }
123 }
124
124
125 /*!
125 /*!
126 Sets the \a brush of legend. Brush affects the background of legend.
126 Sets the \a brush of legend. Brush affects the background of legend.
127 */
127 */
128 void QLegend::setBrush(const QBrush &brush)
128 void QLegend::setBrush(const QBrush &brush)
129 {
129 {
130 if (d_ptr->m_brush != brush) {
130 if (d_ptr->m_brush != brush) {
131 d_ptr->m_brush = brush;
131 d_ptr->m_brush = brush;
132 update();
132 update();
133 }
133 }
134 }
134 }
135
135
136 /*!
136 /*!
137 Returns the brush used by legend.
137 Returns the brush used by legend.
138 */
138 */
139 QBrush QLegend::brush() const
139 QBrush QLegend::brush() const
140 {
140 {
141 return d_ptr->m_brush;
141 return d_ptr->m_brush;
142 }
142 }
143
143
144 /*!
144 /*!
145 Sets the \a pen of legend. Pen affects the legend borders.
145 Sets the \a pen of legend. Pen affects the legend borders.
146 */
146 */
147 void QLegend::setPen(const QPen &pen)
147 void QLegend::setPen(const QPen &pen)
148 {
148 {
149 if (d_ptr->m_pen != pen) {
149 if (d_ptr->m_pen != pen) {
150 d_ptr->m_pen = pen;
150 d_ptr->m_pen = pen;
151 update();
151 update();
152 }
152 }
153 }
153 }
154
154
155 /*!
155 /*!
156 Returns the pen used by legend
156 Returns the pen used by legend
157 */
157 */
158
158
159 QPen QLegend::pen() const
159 QPen QLegend::pen() const
160 {
160 {
161 return d_ptr->m_pen;
161 return d_ptr->m_pen;
162 }
162 }
163
163
164 /*!
164 /*!
165 \property QLegend::alignment
165 \property QLegend::alignment
166 \brief The alignment of the legend.
166 \brief The alignment of the legend.
167 */
167 */
168
168
169 /*!
169 /*!
170 Sets the \a alignment for legend. Legend paints on the defined position in chart. The following alignments are
170 Sets the \a alignment for legend. Legend paints on the defined position in chart. The following alignments are
171 supported: Qt::AlignTop, Qt::AlignBottom, Qt::AlignLeft, Qt::AlignRight. If you set more than one flag the result
171 supported: Qt::AlignTop, Qt::AlignBottom, Qt::AlignLeft, Qt::AlignRight. If you set more than one flag the result
172 is undefined.
172 is undefined.
173
173
174 \sa QLegend::Alignment
174 \sa QLegend::Alignment
175 */
175 */
176 void QLegend::setAlignment(Qt::Alignment alignment)
176 void QLegend::setAlignment(Qt::Alignment alignment)
177 {
177 {
178 if(d_ptr->m_alignment!=alignment) {
178 if(d_ptr->m_alignment!=alignment) {
179 d_ptr->m_alignment = alignment;
179 d_ptr->m_alignment = alignment;
180 d_ptr->updateLayout();
180 d_ptr->updateLayout();
181 alignmentChanged();
181 alignmentChanged();
182 }
182 }
183 }
183 }
184
184
185 /*!
185 /*!
186 Returns the preferred layout for legend
186 Returns the preferred layout for legend
187 */
187 */
188 Qt::Alignment QLegend::alignment() const
188 Qt::Alignment QLegend::alignment() const
189 {
189 {
190 return d_ptr->m_alignment;
190 return d_ptr->m_alignment;
191 }
191 }
192
192
193 /*!
193 /*!
194 Detaches the legend from chart. Chart won't change layout of the legend.
194 Detaches the legend from chart. Chart won't change layout of the legend.
195 */
195 */
196 void QLegend::detachFromChart()
196 void QLegend::detachFromChart()
197 {
197 {
198 d_ptr->m_attachedToChart = false;
198 d_ptr->m_attachedToChart = false;
199 }
199 }
200
200
201 /*!
201 /*!
202 Attaches the legend to chart. Chart may change layout of the legend.
202 Attaches the legend to chart. Chart may change layout of the legend.
203 */
203 */
204 void QLegend::attachToChart()
204 void QLegend::attachToChart()
205 {
205 {
206 d_ptr->attachToChart();
206 d_ptr->attachToChart();
207 }
207 }
208
208
209 /*!
209 /*!
210 Returns true, if legend is attached to chart.
210 Returns true, if legend is attached to chart.
211 */
211 */
212 bool QLegend::isAttachedToChart()
212 bool QLegend::isAttachedToChart()
213 {
213 {
214 return d_ptr->m_attachedToChart;
214 return d_ptr->m_attachedToChart;
215 }
215 }
216
216
217 /*!
217 /*!
218 Sets the legend's scrolling offset to value defined by \a point.
218 Sets the legend's scrolling offset to value defined by \a point.
219 */
219 */
220 void QLegend::setOffset(const QPointF& point)
220 void QLegend::setOffset(const QPointF& point)
221 {
221 {
222 d_ptr->setOffset(point.x(),point.y());
222 d_ptr->setOffset(point.x(),point.y());
223 }
223 }
224
224
225 /*!
225 /*!
226 Returns the legend's scrolling offset.
226 Returns the legend's scrolling offset.
227 */
227 */
228 QPointF QLegend::offset() const
228 QPointF QLegend::offset() const
229 {
229 {
230 return QPointF(d_ptr->m_offsetX,d_ptr->m_offsetY);
230 return QPointF(d_ptr->m_offsetX,d_ptr->m_offsetY);
231 }
231 }
232
232
233 /*!
233 /*!
234 Sets the visibility of legend background to \a visible
234 Sets the visibility of legend background to \a visible
235 */
235 */
236 void QLegend::setBackgroundVisible(bool visible)
236 void QLegend::setBackgroundVisible(bool visible)
237 {
237 {
238 if(d_ptr->m_backgroundVisible!=visible)
238 if(d_ptr->m_backgroundVisible!=visible)
239 {
239 {
240 d_ptr->m_backgroundVisible=visible;
240 d_ptr->m_backgroundVisible=visible;
241 update();
241 update();
242 }
242 }
243 }
243 }
244
244
245 /*!
245 /*!
246 Returns the visibility of legend background
246 Returns the visibility of legend background
247 */
247 */
248 bool QLegend::isBackgroundVisible() const
248 bool QLegend::isBackgroundVisible() const
249 {
249 {
250 return d_ptr->m_backgroundVisible;
250 return d_ptr->m_backgroundVisible;
251 }
251 }
252
252
253 /*!
253 /*!
254 \internal \a event see QGraphicsWidget for details
254 \internal \a event see QGraphicsWidget for details
255 */
255 */
256 void QLegend::resizeEvent(QGraphicsSceneResizeEvent *event)
256 void QLegend::resizeEvent(QGraphicsSceneResizeEvent *event)
257 {
257 {
258 const QRectF& rect = QRectF(QPoint(0,0),event->newSize());
258 const QRectF& rect = QRectF(QPoint(0,0),event->newSize());
259 QGraphicsWidget::resizeEvent(event);
259 QGraphicsWidget::resizeEvent(event);
260 if(d_ptr->m_rect != rect) {
260 if(d_ptr->m_rect != rect) {
261 d_ptr->m_rect = rect;
261 d_ptr->m_rect = rect;
262 d_ptr->updateLayout();
262 d_ptr->updateLayout();
263 }
263 }
264 }
264 }
265
265
266 /*!
266 /*!
267 \internal \a event see QGraphicsWidget for details
267 \internal \a event see QGraphicsWidget for details
268 */
268 */
269 void QLegend::hideEvent(QHideEvent *event)
269 void QLegend::hideEvent(QHideEvent *event)
270 {
270 {
271 QGraphicsWidget::hideEvent(event);
271 QGraphicsWidget::hideEvent(event);
272 setEnabled(false);
272 setEnabled(false);
273 d_ptr->updateLayout();
273 d_ptr->updateLayout();
274 }
274 }
275
275
276 /*!
276 /*!
277 \internal \a event see QGraphicsWidget for details
277 \internal \a event see QGraphicsWidget for details
278 */
278 */
279 void QLegend::showEvent(QShowEvent *event)
279 void QLegend::showEvent(QShowEvent *event)
280 {
280 {
281 QGraphicsWidget::showEvent(event);
281 QGraphicsWidget::showEvent(event);
282 setEnabled(true);
282 setEnabled(true);
283 d_ptr->updateLayout();
283 d_ptr->updateLayout();
284 }
284 }
285
285
286 qreal QLegend::minWidth() const
286 qreal QLegend::minWidth() const
287 {
287 {
288 return d_ptr->m_minWidth;
288 return d_ptr->m_minWidth;
289 }
289 }
290
290
291 qreal QLegend::minHeight() const
291 qreal QLegend::minHeight() const
292 {
292 {
293 return d_ptr->m_minHeight;
293 return d_ptr->m_minHeight;
294 }
294 }
295
295
296 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
296 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
297
297
298 QLegendPrivate::QLegendPrivate(ChartPresenter* presenter, QChart *chart, QLegend *q):
298 QLegendPrivate::QLegendPrivate(ChartPresenter* presenter, QChart *chart, QLegend *q):
299 q_ptr(q),
299 q_ptr(q),
300 m_presenter(presenter),
300 m_presenter(presenter),
301 m_chart(chart),
301 m_chart(chart),
302 m_markers(new QGraphicsItemGroup(q)),
302 m_markers(new QGraphicsItemGroup(q)),
303 m_alignment(Qt::AlignTop),
303 m_alignment(Qt::AlignTop),
304 m_offsetX(0),
304 m_offsetX(0),
305 m_offsetY(0),
305 m_offsetY(0),
306 m_minWidth(0),
306 m_minWidth(0),
307 m_minHeight(0),
307 m_minHeight(0),
308 m_width(0),
308 m_width(0),
309 m_height(0),
309 m_height(0),
310 m_attachedToChart(true),
310 m_attachedToChart(true),
311 m_backgroundVisible(false)
311 m_backgroundVisible(false)
312 {
312 {
313
313
314 }
314 }
315
315
316 QLegendPrivate::~QLegendPrivate()
316 QLegendPrivate::~QLegendPrivate()
317 {
317 {
318
318
319 }
319 }
320
320
321 void QLegendPrivate::setOffset(qreal x, qreal y)
321 void QLegendPrivate::setOffset(qreal x, qreal y)
322 {
322 {
323
323 bool scrollHorizontal = true;
324 switch(m_alignment) {
324 switch(m_alignment) {
325
326 case Qt::AlignTop:
325 case Qt::AlignTop:
327 case Qt::AlignBottom: {
326 case Qt::AlignBottom: {
328 if(m_width<=m_rect.width()) return;
327 scrollHorizontal = true;
329
330 if (x != m_offsetX) {
331 m_offsetX = qBound(qreal(0), x, m_width - m_rect.width());
332 m_markers->setPos(-m_offsetX,m_rect.top());
333 }
334 break;
328 break;
335 }
329 }
336 case Qt::AlignLeft:
330 case Qt::AlignLeft:
337 case Qt::AlignRight: {
331 case Qt::AlignRight: {
332 scrollHorizontal = false;
333 break;
334 }
335 }
338
336
339 if(m_height<=m_rect.height()) return;
337 // If detached, the scrolling and layout logic is inverted.
338 if (!m_attachedToChart) {
339 scrollHorizontal = !scrollHorizontal;
340 }
340
341
341 if (y != m_offsetY) {
342 if (scrollHorizontal) {
342 m_offsetY = qBound(qreal(0), y, m_height - m_rect.height());
343 if(m_width<=m_rect.width()) return;
343 m_markers->setPos(m_rect.left(),-m_offsetY);
344
344 }
345 if (x != m_offsetX) {
345 break;
346 m_offsetX = qBound(qreal(0), x, m_width - m_rect.width());
347 m_markers->setPos(-m_offsetX,m_rect.top());
348 }
349 } else {
350 if(m_height<=m_rect.height()) return;
351
352 if (y != m_offsetY) {
353 m_offsetY = qBound(qreal(0), y, m_height - m_rect.height());
354 m_markers->setPos(m_rect.left(),-m_offsetY);
346 }
355 }
347 }
356 }
348 }
357 }
349
358
350
359
351 void QLegendPrivate::updateLayout()
360 void QLegendPrivate::updateLayout()
352 {
361 {
362 if (!m_attachedToChart) {
363 updateDetachedLayout();
364 return;
365 }
366
353 m_offsetX=0;
367 m_offsetX=0;
354 QList<QGraphicsItem *> items = m_markers->childItems();
368 QList<QGraphicsItem *> items = m_markers->childItems();
355
369
356 if(items.isEmpty()) return;
370 if(items.isEmpty()) return;
357
371
358 m_minWidth=0;
372 m_minWidth=0;
359 m_minHeight=0;
373 m_minHeight=0;
360
374
361 switch(m_alignment) {
375 switch(m_alignment) {
362
376
363 case Qt::AlignTop:
377 case Qt::AlignTop:
364 case Qt::AlignBottom: {
378 case Qt::AlignBottom: {
365 QPointF point = m_rect.topLeft();
379 QPointF point = m_rect.topLeft();
366 m_width = 0;
380 m_width = 0;
367 foreach (QGraphicsItem *item, items) {
381 foreach (QGraphicsItem *item, items) {
368 item->setPos(point.x(),m_rect.height()/2 -item->boundingRect().height()/2);
382 item->setPos(point.x(),m_rect.height()/2 -item->boundingRect().height()/2);
369 const QRectF& rect = item->boundingRect();
383 const QRectF& rect = item->boundingRect();
370 qreal w = rect.width();
384 qreal w = rect.width();
371 m_minWidth=qMax(m_minWidth,w);
385 m_minWidth=qMax(m_minWidth,w);
372 m_minHeight=qMax(m_minHeight,rect.height());
386 m_minHeight=qMax(m_minHeight,rect.height());
373 m_width+=w;
387 m_width+=w;
374 point.setX(point.x() + w);
388 point.setX(point.x() + w);
375 }
389 }
376 if(m_width<m_rect.width()) {
390 if(m_width<m_rect.width()) {
377 m_markers->setPos(m_rect.width()/2-m_width/2,m_rect.top());
391 m_markers->setPos(m_rect.width()/2-m_width/2,m_rect.top());
378 }
392 }
379 else {
393 else {
380 m_markers->setPos(m_rect.topLeft());
394 m_markers->setPos(m_rect.topLeft());
381 }
395 }
382 m_height=m_minHeight;
396 m_height=m_minHeight;
383 }
397 }
384 break;
398 break;
385 case Qt::AlignLeft:
399 case Qt::AlignLeft:
386 case Qt::AlignRight: {
400 case Qt::AlignRight: {
387 QPointF point = m_rect.topLeft();
401 QPointF point = m_rect.topLeft();
388 m_height = 0;
402 m_height = 0;
389 foreach (QGraphicsItem *item, items) {
403 foreach (QGraphicsItem *item, items) {
390 item->setPos(point);
404 item->setPos(point);
391 const QRectF& rect = item->boundingRect();
405 const QRectF& rect = item->boundingRect();
392 qreal h = rect.height();
406 qreal h = rect.height();
393 m_minWidth=qMax(m_minWidth,rect.width());
407 m_minWidth=qMax(m_minWidth,rect.width());
394 m_minHeight=qMax(m_minHeight,h);
408 m_minHeight=qMax(m_minHeight,h);
395 m_height+=h;
409 m_height+=h;
396 point.setY(point.y() + h);
410 point.setY(point.y() + h);
397 }
411 }
398 if(m_height<m_rect.height()) {
412 if(m_height<m_rect.height()) {
399 m_markers->setPos(m_rect.left(),m_rect.height()/2-m_height/2);
413 m_markers->setPos(m_rect.left(),m_rect.height()/2-m_height/2);
400 }
414 }
401 else {
415 else {
402 m_markers->setPos(m_rect.topLeft());
416 m_markers->setPos(m_rect.topLeft());
403 }
417 }
404 m_width=m_minWidth;
418 m_width=m_minWidth;
405 }
419 }
406 break;
420 break;
407 }
421 }
408
422
409 if (m_attachedToChart) {
423 m_presenter->updateLayout();
410 m_presenter->updateLayout();
424 }
425
426 void QLegendPrivate::updateDetachedLayout()
427 {
428 m_offsetX=0;
429 QList<QGraphicsItem *> items = m_markers->childItems();
430
431 if(items.isEmpty()) return;
432
433 m_minWidth = 0;
434 m_minHeight = 0;
435
436 switch (m_alignment) {
437 case Qt::AlignTop: {
438 QPointF point = m_rect.topLeft();
439 m_width = 0;
440 m_height = 0;
441 for (int i=0; i<items.count(); i++) {
442 QGraphicsItem *item = items.at(i);
443 const QRectF& rect = item->boundingRect();
444 qreal w = rect.width();
445 qreal h = rect.height();
446 m_minWidth = qMax(m_minWidth,w);
447 m_minHeight = qMax(m_minHeight,rect.height());
448 m_height = qMax(m_height,h);
449 item->setPos(point.x(),point.y());
450 point.setX(point.x() + w);
451 if (point.x() + w > m_rect.topLeft().x() + m_rect.width()) {
452 // Next item would go off rect.
453 point.setX(m_rect.topLeft().x());
454 point.setY(point.y() + h);
455 if (i+1 < items.count()) {
456 m_height += h;
457 }
458 }
459 }
460 m_markers->setPos(m_rect.topLeft());
461 m_width = m_minWidth;
462 }
463 break;
464 case Qt::AlignBottom: {
465 QPointF point = m_rect.bottomLeft();
466 m_width = 0;
467 m_height = 0;
468 for (int i=0; i<items.count(); i++) {
469 QGraphicsItem *item = items.at(i);
470 const QRectF& rect = item->boundingRect();
471 qreal w = rect.width();
472 qreal h = rect.height();
473 m_minWidth = qMax(m_minWidth,w);
474 m_minHeight = qMax(m_minHeight,rect.height());
475 m_height = qMax(m_height,h);
476 item->setPos(point.x(),point.y() - h);
477 point.setX(point.x() + w);
478 if (point.x() + w > m_rect.bottomLeft().x() + m_rect.width()) {
479 // Next item would go off rect.
480 point.setX(m_rect.bottomLeft().x());
481 point.setY(point.y() - h);
482 if (i+1 < items.count()) {
483 m_height += h;
484 }
485 }
486 }
487 m_markers->setPos(m_rect.topLeft());
488 m_width = m_minWidth;
489 }
490 break;
491 case Qt::AlignLeft: {
492 QPointF point = m_rect.topLeft();
493 m_width = 0;
494 m_height = 0;
495 qreal maxWidth = 0;
496 for (int i=0; i<items.count(); i++) {
497 QGraphicsItem *item = items.at(i);
498 const QRectF& rect = item->boundingRect();
499 qreal w = rect.width();
500 qreal h = rect.height();
501 m_minWidth = qMax(m_minWidth,rect.width());
502 m_minHeight = qMax(m_minHeight,h);
503 maxWidth = qMax(maxWidth,w);
504 m_width = qMax(m_width, maxWidth);
505 item->setPos(point.x(),point.y());
506 point.setY(point.y() + h);
507 if (point.y() + h > m_rect.topLeft().y() + m_rect.height()) {
508 // Next item would go off rect.
509 point.setX(point.x() + maxWidth);
510 point.setY(m_rect.topLeft().y());
511 if (i+1 < items.count()) {
512 m_width += maxWidth;
513 maxWidth = 0;
514 }
515 }
516 }
517 m_markers->setPos(m_rect.topLeft());
518 m_height = m_minHeight;
519 }
520 break;
521 case Qt::AlignRight: {
522 QPointF point = m_rect.topRight();
523 m_width = 0;
524 m_height = 0;
525 qreal maxWidth = 0;
526 for (int i=0; i<items.count(); i++) {
527 QGraphicsItem *item = items.at(i);
528 const QRectF& rect = item->boundingRect();
529 qreal w = rect.width();
530 qreal h = rect.height();
531 m_minWidth = qMax(m_minWidth,rect.width());
532 m_minHeight = qMax(m_minHeight,h);
533 maxWidth = qMax(maxWidth,w);
534 m_width = qMax(m_width, maxWidth);
535 item->setPos(point.x() - w,point.y());
536 point.setY(point.y() + h);
537 if (point.y() + h > m_rect.topLeft().y() + m_rect.height()) {
538 // Next item would go off rect.
539 point.setX(point.x() - maxWidth);
540 point.setY(m_rect.topLeft().y());
541 if (i+1 < items.count()) {
542 m_width += maxWidth;
543 maxWidth = 0;
544 }
545 }
546 }
547 m_markers->setPos(m_rect.topLeft());
548 m_height = m_minHeight;
549 }
550 break;
551 default:
552 break;
411 }
553 }
412 }
554 }
413
555
414 void QLegendPrivate::attachToChart()
556 void QLegendPrivate::attachToChart()
415 {
557 {
416 m_attachedToChart = true;
558 m_attachedToChart = true;
417 q_ptr->setParent(m_chart);
559 q_ptr->setParent(m_chart);
418 }
560 }
419
561
420 void QLegendPrivate::handleSeriesAdded(QAbstractSeries *series, Domain *domain)
562 void QLegendPrivate::handleSeriesAdded(QAbstractSeries *series, Domain *domain)
421 {
563 {
422 Q_UNUSED(domain)
564 Q_UNUSED(domain)
423
565
424 QList<LegendMarker*> markers = series->d_ptr->createLegendMarker(q_ptr);
566 QList<LegendMarker*> markers = series->d_ptr->createLegendMarker(q_ptr);
425 foreach(LegendMarker* marker, markers)
567 foreach(LegendMarker* marker, markers)
426 m_markers->addToGroup(marker);
568 m_markers->addToGroup(marker);
427
569
428 if(series->type() == QAbstractSeries::SeriesTypePie) {
570 if(series->type() == QAbstractSeries::SeriesTypePie) {
429 QPieSeries *pieSeries = static_cast<QPieSeries *>(series);
571 QPieSeries *pieSeries = static_cast<QPieSeries *>(series);
430 QObject::connect(pieSeries, SIGNAL(added(QList<QPieSlice*>)), this, SLOT(handleUpdatePieSeries()));
572 QObject::connect(pieSeries, SIGNAL(added(QList<QPieSlice*>)), this, SLOT(handleUpdatePieSeries()));
431 QObject::connect(pieSeries, SIGNAL(removed(QList<QPieSlice*>)), this, SLOT(handleUpdatePieSeries()));
573 QObject::connect(pieSeries, SIGNAL(removed(QList<QPieSlice*>)), this, SLOT(handleUpdatePieSeries()));
432 }
574 }
433
575
434 updateLayout();
576 updateLayout();
435 }
577 }
436
578
437 void QLegendPrivate::handleSeriesRemoved(QAbstractSeries *series)
579 void QLegendPrivate::handleSeriesRemoved(QAbstractSeries *series)
438 {
580 {
439 QList<QGraphicsItem *> items = m_markers->childItems();
581 QList<QGraphicsItem *> items = m_markers->childItems();
440
582
441 foreach (QGraphicsItem *markers, items) {
583 foreach (QGraphicsItem *markers, items) {
442 LegendMarker *marker = static_cast<LegendMarker*>(markers);
584 LegendMarker *marker = static_cast<LegendMarker*>(markers);
443 if (marker->series() == series) {
585 if (marker->series() == series) {
444 delete marker;
586 delete marker;
445 }
587 }
446 }
588 }
447
589
448 if(series->type() == QAbstractSeries::SeriesTypePie)
590 if(series->type() == QAbstractSeries::SeriesTypePie)
449 {
591 {
450 QPieSeries *pieSeries = static_cast<QPieSeries *>(series);
592 QPieSeries *pieSeries = static_cast<QPieSeries *>(series);
451 QObject::disconnect(pieSeries, SIGNAL(added(QList<QPieSlice*>)), this, SLOT(handleUpdatePieSeries()));
593 QObject::disconnect(pieSeries, SIGNAL(added(QList<QPieSlice*>)), this, SLOT(handleUpdatePieSeries()));
452 QObject::disconnect(pieSeries, SIGNAL(removed(QList<QPieSlice*>)), this, SLOT(handleUpdatePieSeries()));
594 QObject::disconnect(pieSeries, SIGNAL(removed(QList<QPieSlice*>)), this, SLOT(handleUpdatePieSeries()));
453 }
595 }
454
596
455 updateLayout();
597 updateLayout();
456 }
598 }
457
599
458 void QLegendPrivate::handleSeriesUpdated(QAbstractSeries *series)
600 void QLegendPrivate::handleSeriesUpdated(QAbstractSeries *series)
459 {
601 {
460 // TODO: find out which markers are are added or removed. Update them
602 // TODO: find out which markers are are added or removed. Update them
461 // TODO: better implementation
603 // TODO: better implementation
462 handleSeriesRemoved(series);
604 handleSeriesRemoved(series);
463 Domain domain;
605 Domain domain;
464 handleSeriesAdded(series, &domain);
606 handleSeriesAdded(series, &domain);
465 }
607 }
466
608
467 void QLegendPrivate::handleUpdatePieSeries()
609 void QLegendPrivate::handleUpdatePieSeries()
468 {
610 {
469 //TODO: reimplement to be optimal
611 //TODO: reimplement to be optimal
470 QPieSeries* series = qobject_cast<QPieSeries *> (sender());
612 QPieSeries* series = qobject_cast<QPieSeries *> (sender());
471 Q_ASSERT(series);
613 Q_ASSERT(series);
472 handleSeriesRemoved(series);
614 handleSeriesRemoved(series);
473 handleSeriesAdded(series, 0);
615 handleSeriesAdded(series, 0);
474 }
616 }
475
617
476 #include "moc_qlegend.cpp"
618 #include "moc_qlegend.cpp"
477 #include "moc_qlegend_p.cpp"
619 #include "moc_qlegend_p.cpp"
478
620
479 QTCOMMERCIALCHART_END_NAMESPACE
621 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,82 +1,83
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2012 Digia Plc
3 ** Copyright (C) 2012 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
6 **
7 ** This file is part of the Qt Commercial Charts Add-on.
7 ** This file is part of the Qt Commercial Charts Add-on.
8 **
8 **
9 ** $QT_BEGIN_LICENSE$
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Commercial licenses may use this file in
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
13 ** a written agreement between you and Digia.
14 **
14 **
15 ** If you have questions regarding the use of this file, please use
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
17 ** $QT_END_LICENSE$
18 **
18 **
19 ****************************************************************************/
19 ****************************************************************************/
20
20
21 // W A R N I N G
21 // W A R N I N G
22 // -------------
22 // -------------
23 //
23 //
24 // This file is not part of the QtCommercial Chart API. It exists purely as an
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
25 // implementation detail. This header file may change from version to
26 // version without notice, or even be removed.
26 // version without notice, or even be removed.
27 //
27 //
28 // We mean it.
28 // We mean it.
29
29
30 #ifndef QLEGEND_P_H
30 #ifndef QLEGEND_P_H
31 #define QLEGEND_P_H
31 #define QLEGEND_P_H
32
32
33 #include "qlegend.h"
33 #include "qlegend.h"
34
34
35 QTCOMMERCIALCHART_BEGIN_NAMESPACE
35 QTCOMMERCIALCHART_BEGIN_NAMESPACE
36
36
37 class QChart;
37 class QChart;
38 class ChartPresenter;
38 class ChartPresenter;
39 class QAbstractSeries;
39 class QAbstractSeries;
40
40
41 class QLegendPrivate : public QObject
41 class QLegendPrivate : public QObject
42 {
42 {
43 Q_OBJECT
43 Q_OBJECT
44 public:
44 public:
45 QLegendPrivate(ChartPresenter *presenter, QChart *chart, QLegend *q);
45 QLegendPrivate(ChartPresenter *presenter, QChart *chart, QLegend *q);
46 ~QLegendPrivate();
46 ~QLegendPrivate();
47
47
48 void setOffset(qreal x, qreal y);
48 void setOffset(qreal x, qreal y);
49 void updateLayout();
49 void updateLayout();
50 void updateDetachedLayout();
50 void attachToChart();
51 void attachToChart();
51
52
52 public Q_SLOTS:
53 public Q_SLOTS:
53 void handleSeriesAdded(QAbstractSeries *series, Domain *domain);
54 void handleSeriesAdded(QAbstractSeries *series, Domain *domain);
54 void handleSeriesRemoved(QAbstractSeries *series);
55 void handleSeriesRemoved(QAbstractSeries *series);
55 void handleSeriesUpdated(QAbstractSeries *series);
56 void handleSeriesUpdated(QAbstractSeries *series);
56 void handleUpdatePieSeries(); //TODO remove this function
57 void handleUpdatePieSeries(); //TODO remove this function
57
58
58 private:
59 private:
59 QLegend *q_ptr;
60 QLegend *q_ptr;
60 ChartPresenter *m_presenter;
61 ChartPresenter *m_presenter;
61 QChart* m_chart;
62 QChart* m_chart;
62 QGraphicsItemGroup* m_markers;
63 QGraphicsItemGroup* m_markers;
63 Qt::Alignment m_alignment;
64 Qt::Alignment m_alignment;
64 QBrush m_brush;
65 QBrush m_brush;
65 QPen m_pen;
66 QPen m_pen;
66 QRectF m_rect;
67 QRectF m_rect;
67 qreal m_offsetX;
68 qreal m_offsetX;
68 qreal m_offsetY;
69 qreal m_offsetY;
69 qreal m_minWidth;
70 qreal m_minWidth;
70 qreal m_minHeight;
71 qreal m_minHeight;
71 qreal m_width;
72 qreal m_width;
72 qreal m_height;
73 qreal m_height;
73 bool m_attachedToChart;
74 bool m_attachedToChart;
74 bool m_backgroundVisible;
75 bool m_backgroundVisible;
75
76
76 friend class QLegend;
77 friend class QLegend;
77
78
78 };
79 };
79
80
80 QTCOMMERCIALCHART_END_NAMESPACE
81 QTCOMMERCIALCHART_END_NAMESPACE
81
82
82 #endif
83 #endif
General Comments 0
You need to be logged in to leave comments. Login now