##// END OF EJS Templates
legend pos to theme example, legend padding
sauimone -
r803:a2705c21cb29
parent child
Show More
@@ -1,346 +1,367
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE:BSD$
10 10 ** You may use this file under the terms of the BSD license as follows:
11 11 **
12 12 ** "Redistribution and use in source and binary forms, with or without
13 13 ** modification, are permitted provided that the following conditions are
14 14 ** met:
15 15 ** * Redistributions of source code must retain the above copyright
16 16 ** notice, this list of conditions and the following disclaimer.
17 17 ** * Redistributions in binary form must reproduce the above copyright
18 18 ** notice, this list of conditions and the following disclaimer in
19 19 ** the documentation and/or other materials provided with the
20 20 ** distribution.
21 21 ** * Neither the name of Digia nor the names of its contributors
22 22 ** may be used to endorse or promote products derived from this
23 23 ** software without specific prior written permission.
24 24 **
25 25 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 26 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 27 ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 28 ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 29 ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 30 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 31 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 32 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 33 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 34 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 35 ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
36 36 ** $QT_END_LICENSE$
37 37 **
38 38 ****************************************************************************/
39 39
40 40 #include "themewidget.h"
41 41
42 42 #include <QChartView>
43 43 #include <QPieSeries>
44 44 #include <QPieSlice>
45 45 #include <QBarSeries>
46 46 #include <QPercentBarSeries>
47 47 #include <QStackedBarSeries>
48 48 #include <QBarSet>
49 49 #include <QLineSeries>
50 50 #include <QSplineSeries>
51 51 #include <QScatterSeries>
52 52 #include <QAreaSeries>
53 #include <QLegend>
53 54 #include <QGridLayout>
54 55 #include <QFormLayout>
55 56 #include <QComboBox>
56 57 #include <QSpinBox>
57 58 #include <QCheckBox>
58 59 #include <QGroupBox>
59 60 #include <QLabel>
60 61 #include <QTime>
61 62
62 63 ThemeWidget::ThemeWidget(QWidget* parent) :
63 64 QWidget(parent),
64 65 m_listCount(3),
65 66 m_valueMax(100),
66 67 m_valueCount(11),
67 68 m_dataTable(generateRandomData(m_listCount,m_valueMax,m_valueCount)),
68 69 m_themeComboBox(createThemeBox()),
69 70 m_antialiasCheckBox(new QCheckBox("Anti aliasing")),
70 m_animatedComboBox(createAnimationBox())
71 m_animatedComboBox(createAnimationBox()),
72 m_legendComboBox(createLegendBox())
73
71 74 {
72 75
73 76 connectSignals();
74 77 // create layout
75 78 QGridLayout* baseLayout = new QGridLayout();
76 79 QHBoxLayout *settingsLayout = new QHBoxLayout();
77 80 settingsLayout->addWidget(new QLabel("Theme:"));
78 81 settingsLayout->addWidget(m_themeComboBox);
79 82 settingsLayout->addWidget(new QLabel("Animation:"));
80 83 settingsLayout->addWidget(m_animatedComboBox);
84 settingsLayout->addWidget(m_legendComboBox);
81 85 settingsLayout->addWidget(m_antialiasCheckBox);
82 86 settingsLayout->addStretch();
83 87 baseLayout->addLayout(settingsLayout, 0, 0, 1, 3);
84 88
85 89 //create charts
86 90
87 91 QChartView *chartView;
88 92
89 93 chartView = new QChartView(createAreaChart());
90 94 baseLayout->addWidget(chartView, 1, 0);
91 95 m_charts << chartView;
92 96
93 97 chartView = new QChartView(createBarChart(m_valueCount));
94 98 baseLayout->addWidget(chartView, 1, 1);
95 99 m_charts << chartView;
96 100
97 101 chartView = new QChartView(createLineChart());
98 102 baseLayout->addWidget(chartView, 1, 2);
99 103 m_charts << chartView;
100 104
101 105 chartView = new QChartView(createPieChart());
102 106 chartView->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored); // funny things happen if the pie slice labels no not fit the screen...
103 107 baseLayout->addWidget(chartView, 2, 0);
104 108 m_charts << chartView;
105 109
106 110 chartView = new QChartView(createSplineChart());
107 111 baseLayout->addWidget(chartView, 2, 1);
108 112 m_charts << chartView;
109 113
110 114 chartView = new QChartView(createScatterChart());
111 115 baseLayout->addWidget(chartView, 2, 2);
112 116 m_charts << chartView;
113 117
114 118 setLayout(baseLayout);
115 119 }
116 120
117 121 ThemeWidget::~ThemeWidget()
118 122 {
119 123 }
120 124
121 125 void ThemeWidget::connectSignals()
122 126 {
123 127 connect(m_themeComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(updateUI()));
124 128 connect(m_antialiasCheckBox, SIGNAL(toggled(bool)), this, SLOT(updateUI()));
125 129 connect(m_animatedComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(updateUI()));
130 connect(m_legendComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(updateUI()));
126 131 }
127 132
128 133 DataTable ThemeWidget::generateRandomData(int listCount,int valueMax,int valueCount) const
129 134 {
130 135 DataTable dataTable;
131 136
132 137 // set seed for random stuff
133 138 qsrand(QTime(0, 0, 0).secsTo(QTime::currentTime()));
134 139
135 140 // generate random data
136 141 for (int i(0); i < listCount; i++) {
137 142 DataList dataList;
138 143 for (int j(0); j < valueCount; j++) {
139 144 QPointF value(j + (qreal) rand() / (qreal) RAND_MAX, qrand() % valueMax);
140 145 QString label = "Item " + QString::number(i) + ":" + QString::number(j);
141 146 dataList << Data(value, label);
142 147 }
143 148 dataTable << dataList;
144 149 }
145 150
146 151 return dataTable;
147 152 }
148 153
149 154 QComboBox* ThemeWidget::createThemeBox() const
150 155 {
151 156 // settings layout
152 157 QComboBox* themeComboBox = new QComboBox();
153 158 themeComboBox->addItem("Default", QChart::ChartThemeDefault);
154 159 themeComboBox->addItem("Light", QChart::ChartThemeLight);
155 160 themeComboBox->addItem("Blue Cerulean", QChart::ChartThemeBlueCerulean);
156 161 themeComboBox->addItem("Dark", QChart::ChartThemeDark);
157 162 themeComboBox->addItem("Brown Sand", QChart::ChartThemeBrownSand);
158 163 themeComboBox->addItem("Blue NCS", QChart::ChartThemeBlueNcs);
159 164 themeComboBox->addItem("High Contrast", QChart::ChartThemeHighContrast);
160 165 themeComboBox->addItem("Blue Icy", QChart::ChartThemeBlueIcy);
161 166 return themeComboBox;
162 167 }
163 168
164 169 QComboBox* ThemeWidget::createAnimationBox() const
165 170 {
166 171 // settings layout
167 172 QComboBox* animationComboBox = new QComboBox();
168 173 animationComboBox->addItem("No Animations", QChart::NoAnimation);
169 174 animationComboBox->addItem("GridAxis Animations", QChart::GridAxisAnimations);
170 175 animationComboBox->addItem("Series Animations", QChart::SeriesAnimations);
171 176 animationComboBox->addItem("All Animations", QChart::AllAnimations);
172 177 return animationComboBox;
173 178 }
174 179
180 QComboBox* ThemeWidget::createLegendBox() const
181 {
182 QComboBox* legendComboBox = new QComboBox();
183 legendComboBox->addItem("Legend Top", QLegend::AlignmentTop);
184 legendComboBox->addItem("Legend Bottom", QLegend::AlignmentBottom);
185 legendComboBox->addItem("Legend Left", QLegend::AlignmentLeft);
186 legendComboBox->addItem("Legend Right", QLegend::AlignmentRight);
187 return legendComboBox;
188 }
189
175 190 QChart* ThemeWidget::createAreaChart() const
176 191 {
177 192 // area chart
178 193 QChart *chart = new QChart();
179 194 chart->setTitle("Area chart");
180 195 {
181 196 QString name("Series ");
182 197 int nameIndex = 0;
183 198 for (int i(0); i < m_dataTable.count(); i++) {
184 199 QLineSeries *series1 = new QLineSeries(chart);
185 200 QLineSeries *series2 = new QLineSeries(chart);
186 201 foreach (Data data, m_dataTable[i]) {
187 202 series1->append(data.first);
188 203 series2->append(QPointF(data.first.x(), 0.0));
189 204 }
190 205 QAreaSeries *area = new QAreaSeries(series1, series2);
191 206 area->setName(name + QString::number(nameIndex));
192 207 nameIndex++;
193 208 chart->addSeries(area);
194 209 }
195 210 }
196 211 return chart;
197 212 }
198 213
199 214 QChart* ThemeWidget::createBarChart(int valueCount) const
200 215 {
201 216 // bar chart
202 217 QChart* chart = new QChart();
203 218 chart->setTitle("Bar chart");
204 219 {
205 220 QBarCategories categories;
206 221 // TODO: categories
207 222 for (int i(0); i < valueCount; i++)
208 223 categories << QString::number(i);
209 224 // QBarSeries* series = new QBarSeries(categories, chart);
210 225 // QPercentBarSeries* series = new QPercentBarSeries(categories, chart);
211 226 QStackedBarSeries* series = new QStackedBarSeries(categories, chart);
212 227 for (int i(0); i < m_dataTable.count(); i++) {
213 228 QBarSet *set = new QBarSet("Set" + QString::number(i));
214 229 foreach (Data data, m_dataTable[i])
215 230 *set << data.first.y();
216 231 series->appendBarSet(set);
217 232 }
218 233 chart->addSeries(series);
219 234 }
220 235 return chart;
221 236 }
222 237
223 238 QChart* ThemeWidget::createLineChart() const
224 239 {
225 240 // line chart
226 241 QChart* chart = new QChart();
227 242 chart->setTitle("Line chart");
228 243 QString name("Series ");
229 244 int nameIndex = 0;
230 245 foreach (DataList list, m_dataTable) {
231 246 QLineSeries *series = new QLineSeries(chart);
232 247 foreach (Data data, list)
233 248 series->append(data.first);
234 249 series->setName(name + QString::number(nameIndex));
235 250 nameIndex++;
236 251 chart->addSeries(series);
237 252 }
238 253 return chart;
239 254 }
240 255
241 256 QChart* ThemeWidget::createPieChart() const
242 257 {
243 258 // pie chart
244 259 QChart* chart = new QChart();
245 260 chart->setTitle("Pie chart");
246 261 qreal pieSize = 1.0 / m_dataTable.count();
247 262 for (int i = 0; i < m_dataTable.count(); i++) {
248 263 QPieSeries *series = new QPieSeries(chart);
249 264 foreach (Data data, m_dataTable[i]) {
250 265 QPieSlice *slice = series->append(data.first.y(), data.second);
251 266 if (data == m_dataTable[i].first()) {
252 267 slice->setLabelVisible();
253 268 slice->setExploded();
254 269 }
255 270 }
256 271 qreal hPos = (pieSize / 2) + (i / (qreal) m_dataTable.count());
257 272 series->setPieSize(pieSize);
258 273 series->setPiePosition(hPos, 0.5);
259 274 chart->addSeries(series);
260 275 }
261 276
262 277 return chart;
263 278 }
264 279
265 280 QChart* ThemeWidget::createSplineChart() const
266 281 { // spine chart
267 282 QChart* chart = new QChart();
268 283 chart->setTitle("Spline chart");
269 284 QString name("Series ");
270 285 int nameIndex = 0;
271 286 foreach (DataList list, m_dataTable) {
272 287 QSplineSeries *series = new QSplineSeries(chart);
273 288 foreach (Data data, list)
274 289 series->append(data.first);
275 290 series->setName(name + QString::number(nameIndex));
276 291 nameIndex++;
277 292 chart->addSeries(series);
278 293 }
279 294 return chart;
280 295 }
281 296
282 297 QChart* ThemeWidget::createScatterChart() const
283 298 { // scatter chart
284 299 QChart* chart = new QChart();
285 300 chart->setTitle("Scatter chart");
286 301 QString name("Series ");
287 302 int nameIndex = 0;
288 303 foreach (DataList list, m_dataTable) {
289 304 QScatterSeries *series = new QScatterSeries(chart);
290 305 foreach (Data data, list)
291 306 series->append(data.first);
292 307 series->setName(name + QString::number(nameIndex));
293 308 nameIndex++;
294 309 chart->addSeries(series);
295 310 }
296 311 return chart;
297 312 }
298 313
299 314 void ThemeWidget::updateUI()
300 315 {
301 316 QChart::ChartTheme theme = (QChart::ChartTheme) m_themeComboBox->itemData(m_themeComboBox->currentIndex()).toInt();
302 317
303 318 if (m_charts.at(0)->chart()->theme() != theme) {
304 319 foreach (QChartView *chartView, m_charts)
305 320 chartView->chart()->setTheme(theme);
306 321
307 322 QPalette pal = window()->palette();
308 323 if (theme == QChart::ChartThemeLight) {
309 324 pal.setColor(QPalette::Window, QRgb(0xf0f0f0));
310 325 pal.setColor(QPalette::WindowText, QRgb(0x404044));
311 326 } else if (theme == QChart::ChartThemeDark) {
312 327 pal.setColor(QPalette::Window, QRgb(0x121218));
313 328 pal.setColor(QPalette::WindowText, QRgb(0xd6d6d6));
314 329 } else if (theme == QChart::ChartThemeBlueCerulean) {
315 330 pal.setColor(QPalette::Window, QRgb(0x40434a));
316 331 pal.setColor(QPalette::WindowText, QRgb(0xd6d6d6));
317 332 } else if (theme == QChart::ChartThemeBrownSand) {
318 333 pal.setColor(QPalette::Window, QRgb(0x9e8965));
319 334 pal.setColor(QPalette::WindowText, QRgb(0x404044));
320 335 } else if (theme == QChart::ChartThemeBlueNcs) {
321 336 pal.setColor(QPalette::Window, QRgb(0x018bba));
322 337 pal.setColor(QPalette::WindowText, QRgb(0x404044));
323 338 } else if (theme == QChart::ChartThemeHighContrast) {
324 339 pal.setColor(QPalette::Window, QRgb(0xffab03));
325 340 pal.setColor(QPalette::WindowText, QRgb(0x181818));
326 341 } else if (theme == QChart::ChartThemeBlueIcy) {
327 342 pal.setColor(QPalette::Window, QRgb(0xcee7f0));
328 343 pal.setColor(QPalette::WindowText, QRgb(0x404044));
329 344 } else {
330 345 pal.setColor(QPalette::Window, QRgb(0xf0f0f0));
331 346 pal.setColor(QPalette::WindowText, QRgb(0x404044));
332 347 }
333 348 window()->setPalette(pal);
334 349 }
335 350
336 351 bool checked = m_antialiasCheckBox->isChecked();
337 352 foreach (QChartView *chart, m_charts)
338 353 chart->setRenderHint(QPainter::Antialiasing, checked);
339 354
340 355 QChart::AnimationOptions options(m_animatedComboBox->itemData(m_animatedComboBox->currentIndex()).toInt());
341 356 if (m_charts.at(0)->chart()->animationOptions() != options) {
342 357 foreach (QChartView *chartView, m_charts)
343 358 chartView->chart()->setAnimationOptions(options);
344 359 }
360
361 QLegend::Alignments alignment(m_legendComboBox->itemData(m_legendComboBox->currentIndex()).toInt());
362 foreach (QChartView *chartView, m_charts) {
363 qDebug() << alignment;
364 chartView->chart()->legend()->setAlignmnent(alignment);
365 }
345 366 }
346 367
@@ -1,93 +1,95
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE:BSD$
10 10 ** You may use this file under the terms of the BSD license as follows:
11 11 **
12 12 ** "Redistribution and use in source and binary forms, with or without
13 13 ** modification, are permitted provided that the following conditions are
14 14 ** met:
15 15 ** * Redistributions of source code must retain the above copyright
16 16 ** notice, this list of conditions and the following disclaimer.
17 17 ** * Redistributions in binary form must reproduce the above copyright
18 18 ** notice, this list of conditions and the following disclaimer in
19 19 ** the documentation and/or other materials provided with the
20 20 ** distribution.
21 21 ** * Neither the name of Digia nor the names of its contributors
22 22 ** may be used to endorse or promote products derived from this
23 23 ** software without specific prior written permission.
24 24 **
25 25 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 26 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 27 ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 28 ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 29 ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 30 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 31 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 32 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 33 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 34 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 35 ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
36 36 ** $QT_END_LICENSE$
37 37 **
38 38 ****************************************************************************/
39 39
40 40 #ifndef THEMEWINDOW_H_
41 41 #define THEMEWINDOW_H_
42 42 #include <QWidget>
43 43 #include <QChartGlobal>
44 44
45 45 class QComboBox;
46 46 class QCheckBox;
47 47
48 48 QTCOMMERCIALCHART_BEGIN_NAMESPACE
49 49 class QChartView;
50 50 class QChart;
51 51 QTCOMMERCIALCHART_END_NAMESPACE
52 52
53 53 typedef QPair<QPointF, QString> Data;
54 54 typedef QList<Data> DataList;
55 55 typedef QList<DataList> DataTable;
56 56
57 57 QTCOMMERCIALCHART_USE_NAMESPACE
58 58
59 59 class ThemeWidget: public QWidget
60 60 {
61 61 Q_OBJECT
62 62 public:
63 63 explicit ThemeWidget(QWidget *parent = 0);
64 64 ~ThemeWidget();
65 65
66 66 private Q_SLOTS:
67 67 void updateUI();
68 68
69 69 private:
70 70 DataTable generateRandomData(int listCount,int valueMax,int valueCount) const;
71 71 QComboBox* createThemeBox() const;
72 72 QComboBox* createAnimationBox() const;
73 QComboBox* createLegendBox() const;
73 74 void connectSignals();
74 75 QChart* createAreaChart() const;
75 76 QChart* createBarChart(int valueCount) const;
76 77 QChart* createPieChart() const;
77 78 QChart* createLineChart() const;
78 79 QChart* createSplineChart() const;
79 80 QChart* createScatterChart() const;
80 81
81 82 private:
82 83 int m_listCount;
83 84 int m_valueMax;
84 85 int m_valueCount;
85 86 QList<QChartView*> m_charts;
86 87 DataTable m_dataTable;
87 88
88 89 QComboBox *m_themeComboBox;
89 90 QCheckBox *m_antialiasCheckBox;
90 91 QComboBox *m_animatedComboBox;
92 QComboBox *m_legendComboBox;
91 93 };
92 94
93 95 #endif /* THEMEWINDOW_H_ */
@@ -1,450 +1,401
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "qchart.h"
22 #include "qlegend.h"
23 22 #include "qchartaxis.h"
24 23 #include "chartpresenter_p.h"
25 24 #include "chartdataset_p.h"
26 25 #include "charttheme_p.h"
27 26 #include "chartanimator_p.h"
28 27 //series
29 28 #include "qbarseries.h"
30 29 #include "qstackedbarseries.h"
31 30 #include "qpercentbarseries.h"
32 31 #include "qlineseries.h"
33 32 #include "qareaseries.h"
34 33 #include "qpieseries.h"
35 34 #include "qscatterseries.h"
36 35 #include "qsplineseries.h"
37 36 //items
38 37 #include "axisitem_p.h"
39 38 #include "areachartitem_p.h"
40 39 #include "barchartitem_p.h"
41 40 #include "stackedbarchartitem_p.h"
42 41 #include "percentbarchartitem_p.h"
43 42 #include "linechartitem_p.h"
44 43 #include "piechartitem_p.h"
45 44 #include "scatterchartitem_p.h"
46 45 #include "splinechartitem_p.h"
47 46
48 47 QTCOMMERCIALCHART_BEGIN_NAMESPACE
49 48
50 49 ChartPresenter::ChartPresenter(QChart* chart,ChartDataSet* dataset):QObject(chart),
51 50 m_chart(chart),
52 51 m_animator(0),
53 52 m_dataset(dataset),
54 53 m_chartTheme(0),
55 54 m_rect(QRectF(QPoint(0,0),m_chart->size())),
56 55 m_options(QChart::NoAnimation),
57 56 m_themeForce(false),
58 m_padding(50),
59 57 m_backgroundPadding(10)
60 58 {
61 59 createConnections();
62 60 setTheme(QChart::ChartThemeDefault,false);
63 61 }
64 62
65 63 ChartPresenter::~ChartPresenter()
66 64 {
67 65 delete m_chartTheme;
68 66 }
69 67
70 68 void ChartPresenter::createConnections()
71 69 {
72 70 QObject::connect(m_chart,SIGNAL(geometryChanged()),this,SLOT(handleGeometryChanged()));
73 71 QObject::connect(m_dataset,SIGNAL(seriesAdded(QSeries*,Domain*)),this,SLOT(handleSeriesAdded(QSeries*,Domain*)));
74 72 QObject::connect(m_dataset,SIGNAL(seriesRemoved(QSeries*)),this,SLOT(handleSeriesRemoved(QSeries*)));
75 73 QObject::connect(m_dataset,SIGNAL(axisAdded(QChartAxis*,Domain*)),this,SLOT(handleAxisAdded(QChartAxis*,Domain*)));
76 74 QObject::connect(m_dataset,SIGNAL(axisRemoved(QChartAxis*)),this,SLOT(handleAxisRemoved(QChartAxis*)));
77 75 }
78 76
79 77 void ChartPresenter::handleGeometryChanged()
80 78 {
81 79 QRectF rect(QPoint(0,0),m_chart->size());
82 QLegend* legend = m_chart->legend();
83 if ((legend->attachedToChart()) && (legend->isVisible())) {
84
85 // Reserve some space for legend
86 switch (m_chart->legend()->alignment()) {
87 case QLegend::AlignmentTop: {
88 rect.adjust(m_padding,
89 m_padding + legend->size().height(),
90 -m_padding,
91 -m_padding);
92 break;
93 }
94 case QLegend::AlignmentBottom: {
95 rect.adjust(m_padding,
96 m_padding,
97 -m_padding,
98 -m_padding - legend->size().height());
99 break;
100 }
101 case QLegend::AlignmentLeft: {
102 rect.adjust(m_padding + legend->size().width(),
103 m_padding,
104 -m_padding,
105 -m_padding);
106 break;
107 }
108 case QLegend::AlignmentRight: {
109 rect.adjust(m_padding,
110 m_padding,
111 -m_padding - legend->size().width(),
112 -m_padding);
113 break;
114 }
115 default: {
116 rect.adjust(m_padding,
117 m_padding,
118 -m_padding,
119 -m_padding);
120 break;
121 }
122 }
123 } else {
124
125 // Legend is detached, or not visible
126 rect.adjust(m_padding,
127 m_padding,
128 -m_padding,
129 -m_padding);
130 }
80 QRectF padding = m_chart->padding();
81 rect.adjust(padding.left(), padding.top(), -padding.right(), -padding.bottom());
131 82
132 83 //rewrite zoom stack
133 84 /*
134 85 for(int i=0;i<m_zoomStack.count();i++){
135 86 QRectF r = m_zoomStack[i];
136 87 qreal w = rect.width()/m_rect.width();
137 88 qreal h = rect.height()/m_rect.height();
138 89 QPointF tl = r.topLeft();
139 90 tl.setX(tl.x()*w);
140 91 tl.setY(tl.y()*h);
141 92 QPointF br = r.bottomRight();
142 93 br.setX(br.x()*w);
143 94 br.setY(br.y()*h);
144 95 r.setTopLeft(tl);
145 96 r.setBottomRight(br);
146 97 m_zoomStack[i]=r;
147 98 }
148 99 */
149 100 m_rect = rect;
150 101 Q_ASSERT(m_rect.isValid());
151 102 emit geometryChanged(m_rect);
152 103 }
153 104
154 105 void ChartPresenter::handleAxisAdded(QChartAxis* axis,Domain* domain)
155 106 {
156 107 Axis* item = new Axis(axis,this,axis==m_dataset->axisX()?Axis::X_AXIS : Axis::Y_AXIS);
157 108
158 109 if(m_options.testFlag(QChart::GridAxisAnimations)){
159 110 m_animator->addAnimation(item);
160 111 }
161 112
162 113 if(axis==m_dataset->axisX()){
163 114 m_chartTheme->decorate(axis,true,m_themeForce);
164 115 QObject::connect(domain,SIGNAL(rangeXChanged(qreal,qreal,int)),item,SLOT(handleRangeChanged(qreal,qreal,int)));
165 116 //initialize
166 117 item->handleRangeChanged(domain->minX(),domain->maxX(),domain->tickXCount());
167 118
168 119 }
169 120 else{
170 121 m_chartTheme->decorate(axis,false,m_themeForce);
171 122 QObject::connect(domain,SIGNAL(rangeYChanged(qreal,qreal,int)),item,SLOT(handleRangeChanged(qreal,qreal,int)));
172 123 //initialize
173 124 item->handleRangeChanged(domain->minY(),domain->maxY(),domain->tickYCount());
174 125 }
175 126
176 127 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),item,SLOT(handleGeometryChanged(const QRectF&)));
177 128 //initialize
178 129 item->handleGeometryChanged(m_rect);
179 130 m_axisItems.insert(axis, item);
180 131 }
181 132
182 133 void ChartPresenter::handleAxisRemoved(QChartAxis* axis)
183 134 {
184 135 Axis* item = m_axisItems.take(axis);
185 136 Q_ASSERT(item);
186 137 if(m_animator) m_animator->removeAnimation(item);
187 138 delete item;
188 139 }
189 140
190 141
191 142 void ChartPresenter::handleSeriesAdded(QSeries* series,Domain* domain)
192 143 {
193 144 Chart *item = 0 ;
194 145
195 146 switch(series->type())
196 147 {
197 148 case QSeries::SeriesTypeLine: {
198 149
199 150 QLineSeries* lineSeries = static_cast<QLineSeries*>(series);
200 151 LineChartItem* line = new LineChartItem(lineSeries,this);
201 152 if(m_options.testFlag(QChart::SeriesAnimations)) {
202 153 m_animator->addAnimation(line);
203 154 }
204 155 m_chartTheme->decorate(lineSeries, m_dataset->seriesIndex(series),m_themeForce);
205 156 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),line,SLOT(handleGeometryChanged(const QRectF&)));
206 157 QObject::connect(domain,SIGNAL(domainChanged(qreal,qreal,qreal,qreal)),line,SLOT(handleDomainChanged(qreal,qreal,qreal,qreal)));
207 158 item = line;
208 159 break;
209 160 }
210 161
211 162 case QSeries::SeriesTypeArea: {
212 163
213 164 QAreaSeries* areaSeries = static_cast<QAreaSeries*>(series);
214 165 AreaChartItem* area = new AreaChartItem(areaSeries,this);
215 166 if(m_options.testFlag(QChart::SeriesAnimations)) {
216 167 m_animator->addAnimation(area->upperLineItem());
217 168 if(areaSeries->lowerSeries()) m_animator->addAnimation(area->lowerLineItem());
218 169 }
219 170 m_chartTheme->decorate(areaSeries, m_dataset->seriesIndex(series),m_themeForce);
220 171 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),area,SLOT(handleGeometryChanged(const QRectF&)));
221 172 QObject::connect(domain,SIGNAL(domainChanged(qreal,qreal,qreal,qreal)),area,SLOT(handleDomainChanged(qreal,qreal,qreal,qreal)));
222 173 item=area;
223 174 break;
224 175 }
225 176
226 177 case QSeries::SeriesTypeBar: {
227 178 QBarSeries* barSeries = static_cast<QBarSeries*>(series);
228 179 BarChartItem* bar = new BarChartItem(barSeries,this);
229 180 if(m_options.testFlag(QChart::SeriesAnimations)) {
230 181 m_animator->addAnimation(bar);
231 182 }
232 183 m_chartTheme->decorate(barSeries, m_dataset->seriesIndex(barSeries),m_themeForce);
233 184 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),bar,SLOT(handleGeometryChanged(const QRectF&)));
234 185 QObject::connect(domain,SIGNAL(domainChanged(qreal,qreal,qreal,qreal)),bar,SLOT(handleDomainChanged(qreal,qreal,qreal,qreal)));
235 186 item=bar;
236 187 break;
237 188 }
238 189
239 190 case QSeries::SeriesTypeStackedBar: {
240 191 QStackedBarSeries* stackedBarSeries = static_cast<QStackedBarSeries*>(series);
241 192 StackedBarChartItem* bar = new StackedBarChartItem(stackedBarSeries,this);
242 193 if(m_options.testFlag(QChart::SeriesAnimations)) {
243 194 m_animator->addAnimation(bar);
244 195 }
245 196 m_chartTheme->decorate(stackedBarSeries, m_dataset->seriesIndex(stackedBarSeries),m_themeForce);
246 197 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),bar,SLOT(handleGeometryChanged(const QRectF&)));
247 198 QObject::connect(domain,SIGNAL(domainChanged(qreal,qreal,qreal,qreal)),bar,SLOT(handleDomainChanged(qreal,qreal,qreal,qreal)));
248 199 item=bar;
249 200 break;
250 201 }
251 202
252 203 case QSeries::SeriesTypePercentBar: {
253 204 QPercentBarSeries* percentBarSeries = static_cast<QPercentBarSeries*>(series);
254 205 PercentBarChartItem* bar = new PercentBarChartItem(percentBarSeries,this);
255 206 if(m_options.testFlag(QChart::SeriesAnimations)) {
256 207 m_animator->addAnimation(bar);
257 208 }
258 209 m_chartTheme->decorate(percentBarSeries, m_dataset->seriesIndex(percentBarSeries),m_themeForce);
259 210 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),bar,SLOT(handleGeometryChanged(const QRectF&)));
260 211 QObject::connect(domain,SIGNAL(domainChanged(qreal,qreal,qreal,qreal)),bar,SLOT(handleDomainChanged(qreal,qreal,qreal,qreal)));
261 212 item=bar;
262 213 break;
263 214 }
264 215
265 216 case QSeries::SeriesTypeScatter: {
266 217 QScatterSeries *scatterSeries = static_cast<QScatterSeries *>(series);
267 218 ScatterChartItem *scatter = new ScatterChartItem(scatterSeries,this);
268 219 if(m_options.testFlag(QChart::SeriesAnimations)) {
269 220 m_animator->addAnimation(scatter);
270 221 }
271 222 m_chartTheme->decorate(scatterSeries, m_dataset->seriesIndex(series),m_themeForce);
272 223 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),scatter,SLOT(handleGeometryChanged(const QRectF&)));
273 224 QObject::connect(domain,SIGNAL(domainChanged(qreal,qreal,qreal,qreal)),scatter,SLOT(handleDomainChanged(qreal,qreal,qreal,qreal)));
274 225 item = scatter;
275 226 break;
276 227 }
277 228
278 229 case QSeries::SeriesTypePie: {
279 230 QPieSeries *pieSeries = static_cast<QPieSeries *>(series);
280 231 PieChartItem* pie = new PieChartItem(pieSeries, this);
281 232 if(m_options.testFlag(QChart::SeriesAnimations)) {
282 233 m_animator->addAnimation(pie);
283 234 }
284 235 m_chartTheme->decorate(pieSeries, m_dataset->seriesIndex(series),m_themeForce);
285 236 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),pie,SLOT(handleGeometryChanged(const QRectF&)));
286 237 QObject::connect(domain,SIGNAL(domainChanged(qreal,qreal,qreal,qreal)),pie,SLOT(handleDomainChanged(qreal,qreal,qreal,qreal)));
287 238 // Hide all from background when there is only piechart
288 239 // TODO: refactor this ugly code... should be one setting for this
289 240 if (m_chartItems.count() == 0) {
290 241 m_chart->axisX()->hide();
291 242 m_chart->axisY()->hide();
292 243 }
293 244 item=pie;
294 245 break;
295 246 }
296 247
297 248 case QSeries::SeriesTypeSpline: {
298 249 QSplineSeries* splineSeries = static_cast<QSplineSeries*>(series);
299 250 SplineChartItem* spline = new SplineChartItem(splineSeries, this);
300 251 if(m_options.testFlag(QChart::SeriesAnimations)) {
301 252 m_animator->addAnimation(spline);
302 253 }
303 254 m_chartTheme->decorate(splineSeries, m_dataset->seriesIndex(series),m_themeForce);
304 255 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),spline,SLOT(handleGeometryChanged(const QRectF&)));
305 256 QObject::connect(domain,SIGNAL(domainChanged(qreal,qreal,qreal,qreal)),spline,SLOT(handleDomainChanged(qreal,qreal,qreal,qreal)));
306 257 item=spline;
307 258 break;
308 259 }
309 260 default: {
310 261 qDebug()<< "Series type" << series->type() << "not implemented.";
311 262 break;
312 263 }
313 264 }
314 265
315 266 //initialize
316 267 item->handleDomainChanged(domain->minX(),domain->maxX(),domain->minY(),domain->maxY());
317 268 if(m_rect.isValid()) item->handleGeometryChanged(m_rect);
318 269 m_chartItems.insert(series,item);
319 270 }
320 271
321 272 void ChartPresenter::handleSeriesRemoved(QSeries* series)
322 273 {
323 274 Chart* item = m_chartItems.take(series);
324 275 Q_ASSERT(item);
325 276 if(m_animator) {
326 277 //small hack to handle area animations
327 278 if(series->type()==QSeries::SeriesTypeArea){
328 279 QAreaSeries* areaSeries = static_cast<QAreaSeries*>(series);
329 280 AreaChartItem* area = static_cast<AreaChartItem*>(item);
330 281 m_animator->removeAnimation(area->upperLineItem());
331 282 if(areaSeries->lowerSeries()) m_animator->removeAnimation(area->lowerLineItem());
332 283 }else
333 284 m_animator->removeAnimation(item);
334 285 }
335 286 delete item;
336 287 }
337 288
338 289 void ChartPresenter::setTheme(QChart::ChartTheme theme,bool force)
339 290 {
340 291 if(m_chartTheme && m_chartTheme->id() == theme) return;
341 292 delete m_chartTheme;
342 293 m_themeForce = force;
343 294 m_chartTheme = ChartTheme::createTheme(theme);
344 295 m_chartTheme->decorate(m_chart,m_themeForce);
345 296 m_chartTheme->decorate(m_chart->legend(),m_themeForce);
346 297 resetAllElements();
347 298 }
348 299
349 300 QChart::ChartTheme ChartPresenter::theme()
350 301 {
351 302 return m_chartTheme->id();
352 303 }
353 304
354 305 void ChartPresenter::setAnimationOptions(QChart::AnimationOptions options)
355 306 {
356 307 if(m_options!=options) {
357 308
358 309 m_options=options;
359 310
360 311 if(m_options!=QChart::NoAnimation && !m_animator) {
361 312 m_animator= new ChartAnimator(this);
362 313
363 314 }
364 315 resetAllElements();
365 316 }
366 317
367 318 }
368 319
369 320 void ChartPresenter::resetAllElements()
370 321 {
371 322 QList<QChartAxis*> axisList = m_axisItems.uniqueKeys();
372 323 QList<QSeries*> seriesList = m_chartItems.uniqueKeys();
373 324
374 325 foreach(QChartAxis* axis, axisList) {
375 326 handleAxisRemoved(axis);
376 327 handleAxisAdded(axis,m_dataset->domain(axis));
377 328 }
378 329 foreach(QSeries* series, seriesList) {
379 330 handleSeriesRemoved(series);
380 331 handleSeriesAdded(series,m_dataset->domain(series));
381 332 }
382 333 }
383 334
384 335 void ChartPresenter::zoomIn()
385 336 {
386 337 QRectF rect = geometry();
387 338 rect.setWidth(rect.width()/2);
388 339 rect.setHeight(rect.height()/2);
389 340 rect.moveCenter(geometry().center());
390 341 zoomIn(rect);
391 342 }
392 343
393 344 void ChartPresenter::zoomIn(const QRectF& rect)
394 345 {
395 346 QRectF r = rect.normalized();
396 r.translate(-m_padding, -m_padding);
347 r.translate(-m_chart->padding().topLeft());
397 348 if(m_animator) {
398 349
399 350 QPointF point(r.center().x()/geometry().width(),r.center().y()/geometry().height());
400 351 m_animator->setState(ChartAnimator::ZoomInState,point);
401 352 }
402 353 m_dataset->zoomInDomain(r,geometry().size());
403 354 if(m_animator) {
404 355 m_animator->setState(ChartAnimator::ShowState);
405 356 }
406 357 }
407 358
408 359 void ChartPresenter::zoomOut()
409 360 {
410 361 if(m_animator)
411 362 {
412 363 m_animator->setState(ChartAnimator::ZoomOutState);
413 364 }
414 365
415 366 QSizeF size = geometry().size();
416 367 QRectF rect = geometry();
417 rect.translate(-m_padding, -m_padding);
368 rect.translate(-m_chart->padding().topLeft());
418 369 m_dataset->zoomOutDomain(rect.adjusted(size.width()/4,size.height()/4,-size.width()/4,-size.height()/4),size);
419 370 //m_dataset->zoomOutDomain(m_zoomStack[m_zoomIndex-1],geometry().size());
420 371
421 372 if(m_animator){
422 373 m_animator->setState(ChartAnimator::ShowState);
423 374 }
424 375 }
425 376
426 377 void ChartPresenter::scroll(int dx,int dy)
427 378 {
428 379 if(m_animator){
429 380 if(dx<0) m_animator->setState(ChartAnimator::ScrollLeftState,QPointF());
430 381 if(dx>0) m_animator->setState(ChartAnimator::ScrollRightState,QPointF());
431 382 if(dy<0) m_animator->setState(ChartAnimator::ScrollUpState,QPointF());
432 383 if(dy>0) m_animator->setState(ChartAnimator::ScrollDownState,QPointF());
433 384 }
434 385
435 386 m_dataset->scrollDomain(dx,dy,geometry().size());
436 387
437 388 if(m_animator){
438 389 m_animator->setState(ChartAnimator::ShowState);
439 390 }
440 391 }
441 392
442 393 QChart::AnimationOptions ChartPresenter::animationOptions() const
443 394 {
444 395 return m_options;
445 396 }
446 397
447 398
448 399 #include "moc_chartpresenter_p.cpp"
449 400
450 401 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,108 +1,106
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #ifndef CHARTPRESENTER_H_
22 22 #define CHARTPRESENTER_H_
23 23
24 24 #include "qchartglobal.h"
25 25 #include "qchart.h" //becouse of QChart::ChartThemeId //TODO
26 26 #include "qchartaxis.h"
27 27 #include <QRectF>
28 28
29 29 QTCOMMERCIALCHART_BEGIN_NAMESPACE
30 30
31 31 class Chart;
32 32 class QSeries;
33 33 class ChartDataSet;
34 34 class Domain;
35 35 class Axis;
36 36 class ChartTheme;
37 37 class ChartAnimator;
38 38
39 39 class ChartPresenter: public QObject
40 40 {
41 41 Q_OBJECT
42 42 public:
43 43 enum ZValues {
44 44 BackgroundZValue = -1,
45 45 ShadesZValue,
46 46 GridZValue,
47 47 LineChartZValue,
48 48 BarSeriesZValue,
49 49 ScatterSeriesZValue,
50 50 PieSeriesZValue,
51 51 AxisZValue,
52 52 LegendZValue
53 53 };
54 54
55 55 ChartPresenter(QChart* chart,ChartDataSet *dataset);
56 56 virtual ~ChartPresenter();
57 57
58 int padding() const { return m_padding; }
59 58 int backgroundPadding() const { return m_backgroundPadding; }
60 59 QRectF geometry() const { return m_rect; }
61 60 ChartAnimator* animator() const { return m_animator; }
62 61 ChartTheme *chartTheme() const { return m_chartTheme; }
63 62 ChartDataSet *dataSet() const { return m_dataset; }
64 63 QGraphicsItem* rootItem() const { return m_chart; }
65 64
66 65 void setTheme(QChart::ChartTheme theme,bool force = true);
67 66 QChart::ChartTheme theme();
68 67
69 68 void setAnimationOptions(QChart::AnimationOptions options);
70 69 QChart::AnimationOptions animationOptions() const;
71 70
72 71 void zoomIn();
73 72 void zoomIn(const QRectF& rect);
74 73 void zoomOut();
75 74 void scroll(int dx,int dy);
76 75
77 76 private:
78 77 void createConnections();
79 78 void resetAllElements();
80 79
81 80 public Q_SLOTS:
82 81 void handleSeriesAdded(QSeries* series,Domain* domain);
83 82 void handleSeriesRemoved(QSeries* series);
84 83 void handleAxisAdded(QChartAxis* axis,Domain* domain);
85 84 void handleAxisRemoved(QChartAxis* axis);
86 85 void handleGeometryChanged();
87 86
88 87 Q_SIGNALS:
89 88 void geometryChanged(const QRectF& rect);
90 89
91 90 private:
92 91 QChart* m_chart;
93 92 ChartAnimator* m_animator;
94 93 ChartDataSet* m_dataset;
95 94 ChartTheme *m_chartTheme;
96 95 QMap<QSeries*,Chart*> m_chartItems;
97 96 QMap<QChartAxis*,Axis*> m_axisItems;
98 97 QRectF m_rect;
99 98 QChart::AnimationOptions m_options;
100 99 bool m_themeForce;
101 int m_padding;
102 100 int m_backgroundPadding;
103 101
104 102 };
105 103
106 104 QTCOMMERCIALCHART_END_NAMESPACE
107 105
108 106 #endif /* CHARTPRESENTER_H_ */
@@ -1,441 +1,501
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "qchart.h"
22 22 #include "qchart_p.h"
23 23 #include <QGraphicsScene>
24 24 #include <QGraphicsSceneResizeEvent>
25 25
26 26 QTCOMMERCIALCHART_BEGIN_NAMESPACE
27 27
28 28 /*!
29 29 \enum QChart::ChartTheme
30 30
31 31 This enum describes the theme used by the chart.
32 32
33 33 \value ChartThemeDefault Follows the GUI style of the Operating System
34 34 \value ChartThemeLight
35 35 \value ChartThemeBlueCerulean
36 36 \value ChartThemeDark
37 37 \value ChartThemeBrownSand
38 38 \value ChartThemeBlueNcs
39 39 \value ChartThemeHighContrast
40 40 \value ChartThemeBlueIcy
41 41 \value ChartThemeCount Not really a theme; the total count of themes.
42 42 */
43 43
44 44 /*!
45 45 \enum QChart::AnimationOption
46 46
47 47 For enabling/disabling animations. Defaults to NoAnimation.
48 48
49 49 \value NoAnimation
50 50 \value GridAxisAnimations
51 51 \value SeriesAnimations
52 52 \value AllAnimations
53 53 */
54 54
55 55 /*!
56 56 \class QChart
57 57 \brief QtCommercial chart API.
58 58
59 59 QChart is a QGraphicsWidget that you can show in a QGraphicsScene. It manages the graphical
60 60 representation of different types of QChartSeries and other chart related objects like
61 61 QChartAxis and QChartLegend. If you simply want to show a chart in a layout, you can use the
62 62 convenience class QChartView instead of QChart.
63 63 \sa QChartView
64 64 */
65 65
66 66 /*!
67 67 Constructs a chart object which is a child of a\a parent. Parameter \a wFlags is passed to the QGraphicsWidget constructor.
68 68 */
69 69 QChart::QChart(QGraphicsItem *parent, Qt::WindowFlags wFlags) : QGraphicsWidget(parent,wFlags),
70 70 d_ptr(new QChartPrivate(this))
71 71 {
72 72 //setMinimumSize(200,200);
73 73 d_ptr->m_legend = new QLegend(this);
74 74 d_ptr->m_dataset = new ChartDataSet(this);
75 75 d_ptr->m_presenter = new ChartPresenter(this,d_ptr->m_dataset);
76 int padding = d_ptr->m_presenter->padding();
77 setMinimumSize(3*padding,3*padding);
76 setMinimumSize(d_ptr->m_padding.left() * 3, d_ptr->m_padding.top() * 3);
78 77 connect(d_ptr->m_dataset,SIGNAL(seriesAdded(QSeries*,Domain*)),d_ptr->m_legend,SLOT(handleSeriesAdded(QSeries*,Domain*)));
79 78 connect(d_ptr->m_dataset,SIGNAL(seriesRemoved(QSeries*)),d_ptr->m_legend,SLOT(handleSeriesRemoved(QSeries*)));
80 79 }
81 80
82 81 /*!
83 82 Destroys the object and it's children, like QChartSeries and QChartAxis object added to it.
84 83 */
85 84 QChart::~QChart()
86 85 {
87 86 //delete first presenter , since this is a root of all the graphical items
88 87 delete d_ptr->m_presenter;
89 88 d_ptr->m_presenter=0;
90 89 }
91 90
92 91 /*!
93 92 Adds the \a series and optional \a axisY onto the chart and takes the ownership of the objects.
94 93 If auto scaling is enabled, re-scales the axes the series is bound to (both the x axis and
95 94 the y axis).
96 95 */
97 96 void QChart::addSeries(QSeries* series, QChartAxis* axisY)
98 97 {
99 98 d_ptr->m_dataset->addSeries(series, axisY);
100 99 }
101 100
102 101 /*!
103 102 Removes the \a series specified in a perameter from the QChartView.
104 103 It releses its ownership of the specified QChartSeries object.
105 104 It does not delete the pointed QChartSeries data object
106 105 \sa addSeries(), removeAllSeries()
107 106 */
108 107 void QChart::removeSeries(QSeries* series)
109 108 {
110 109 d_ptr->m_dataset->removeSeries(series);
111 110 }
112 111
113 112 /*!
114 113 Removes all the QChartSeries that have been added to the QChartView
115 114 It also deletes the pointed QChartSeries data objects
116 115 \sa addSeries(), removeSeries()
117 116 */
118 117 void QChart::removeAllSeries()
119 118 {
120 119 d_ptr->m_dataset->removeAllSeries();
121 120 }
122 121
123 122 /*!
124 123 Sets the \a brush that is used for painting the background of the chart area.
125 124 */
126 125 void QChart::setBackgroundBrush(const QBrush& brush)
127 126 {
128 127 d_ptr->createChartBackgroundItem();
129 128 d_ptr->m_backgroundItem->setBrush(brush);
130 129 d_ptr->m_backgroundItem->update();
131 130 }
132 131
133 132 QBrush QChart::backgroundBrush() const
134 133 {
135 134 if (!d_ptr->m_backgroundItem) return QBrush();
136 135 return (d_ptr->m_backgroundItem)->brush();
137 136 }
138 137
139 138 /*!
140 139 Sets the \a pen that is used for painting the background of the chart area.
141 140 */
142 141 void QChart::setBackgroundPen(const QPen& pen)
143 142 {
144 143 d_ptr->createChartBackgroundItem();
145 144 d_ptr->m_backgroundItem->setPen(pen);
146 145 d_ptr->m_backgroundItem->update();
147 146 }
148 147
149 148 QPen QChart::backgroundPen() const
150 149 {
151 150 if (!d_ptr->m_backgroundItem) return QPen();
152 151 return d_ptr->m_backgroundItem->pen();
153 152 }
154 153
155 154 /*!
156 155 Sets the chart \a title. The description text that is drawn above the chart.
157 156 */
158 157 void QChart::setTitle(const QString& title)
159 158 {
160 159 d_ptr->createChartTitleItem();
161 160 d_ptr->m_titleItem->setText(title);
162 161 d_ptr->updateLayout();
163 162 }
164 163
165 164 /*!
166 165 Returns the chart title. The description text that is drawn above the chart.
167 166 */
168 167 QString QChart::title() const
169 168 {
170 169 if (d_ptr->m_titleItem)
171 170 return d_ptr->m_titleItem->text();
172 171 else
173 172 return QString();
174 173 }
175 174
176 175 /*!
177 176 Sets the \a font that is used for rendering the description text that is rendered above the chart.
178 177 */
179 178 void QChart::setTitleFont(const QFont& font)
180 179 {
181 180 d_ptr->createChartTitleItem();
182 181 d_ptr->m_titleItem->setFont(font);
183 182 d_ptr->updateLayout();
184 183 }
185 184
186 185 /*!
187 186 Sets the \a brush used for rendering the title text.
188 187 */
189 188 void QChart::setTitleBrush(const QBrush &brush)
190 189 {
191 190 d_ptr->createChartTitleItem();
192 191 d_ptr->m_titleItem->setBrush(brush);
193 192 d_ptr->updateLayout();
194 193 }
195 194
196 195 /*!
197 196 Returns the brush used for rendering the title text.
198 197 */
199 198 QBrush QChart::titleBrush() const
200 199 {
201 200 if (!d_ptr->m_titleItem) return QBrush();
202 201 return d_ptr->m_titleItem->brush();
203 202 }
204 203
205 204 /*!
206 205 Sets the \a theme used by the chart for rendering the graphical representation of the data
207 206 \sa ChartTheme, chartTheme()
208 207 */
209 208 void QChart::setTheme(QChart::ChartTheme theme)
210 209 {
211 210 d_ptr->m_presenter->setTheme(theme);
212 211 }
213 212
214 213 /*!
215 214 Returns the theme enum used by the chart.
216 215 \sa ChartTheme, setChartTheme()
217 216 */
218 217 QChart::ChartTheme QChart::theme() const
219 218 {
220 219 return d_ptr->m_presenter->theme();
221 220 }
222 221
223 222 /*!
224 223 Zooms in the view by a factor of 2
225 224 */
226 225 void QChart::zoomIn()
227 226 {
228 227 d_ptr->m_presenter->zoomIn();
229 228 }
230 229
231 230 /*!
232 231 Zooms in the view to a maximum level at which \a rect is still fully visible.
233 232 */
234 233 void QChart::zoomIn(const QRectF& rect)
235 234 {
236 235 if (!rect.isValid()) return;
237 236 d_ptr->m_presenter->zoomIn(rect);
238 237 }
239 238
240 239 /*!
241 240 Restores the view zoom level to the previous one.
242 241 */
243 242 void QChart::zoomOut()
244 243 {
245 244 d_ptr->m_presenter->zoomOut();
246 245 }
247 246
248 247 /*!
249 248 Returns the pointer to the x axis object of the chart
250 249 */
251 250 QChartAxis* QChart::axisX() const
252 251 {
253 252 return d_ptr->m_dataset->axisX();
254 253 }
255 254
256 255 /*!
257 256 Returns the pointer to the y axis object of the chart
258 257 */
259 258 QChartAxis* QChart::axisY() const
260 259 {
261 260 return d_ptr->m_dataset->axisY();
262 261 }
263 262
264 263 /*!
265 264 Returns the legend object of the chart. Ownership stays in chart.
266 265 */
267 266 QLegend* QChart::legend() const
268 267 {
269 268 return d_ptr->m_legend;
270 269 }
271 270
271 QRectF QChart::padding() const
272 {
273 return d_ptr->m_padding;
274 }
275
276
272 277 /*!
273 278 Resizes and updates the chart area using the \a event data
274 279 */
275 280 void QChart::resizeEvent(QGraphicsSceneResizeEvent *event)
276 281 {
277 282 d_ptr->m_rect = QRectF(QPoint(0,0),event->newSize());
278 283 d_ptr->updateLayout();
279 284 QGraphicsWidget::resizeEvent(event);
280 285 update();
281 286 }
282 287
283 288 /*!
284 289 Sets animation \a options for the chart
285 290 */
286 291 void QChart::setAnimationOptions(AnimationOptions options)
287 292 {
288 293 d_ptr->m_presenter->setAnimationOptions(options);
289 294 }
290 295
291 296 /*!
292 297 Returns animation options for the chart
293 298 */
294 299 QChart::AnimationOptions QChart::animationOptions() const
295 300 {
296 301 return d_ptr->m_presenter->animationOptions();
297 302 }
298 303
299 304 void QChart::scrollLeft()
300 305 {
301 306 d_ptr->m_presenter->scroll(-d_ptr->m_presenter->geometry().width()/(axisX()->ticksCount()-1),0);
302 307 }
303 308
304 309 void QChart::scrollRight()
305 310 {
306 311 d_ptr->m_presenter->scroll(d_ptr->m_presenter->geometry().width()/(axisX()->ticksCount()-1),0);
307 312 }
308 313
309 314 void QChart::scrollUp()
310 315 {
311 316 d_ptr->m_presenter->scroll(0,d_ptr->m_presenter->geometry().width()/(axisY()->ticksCount()-1));
312 317 }
313 318
314 319 void QChart::scrollDown()
315 320 {
316 321 d_ptr->m_presenter->scroll(0,-d_ptr->m_presenter->geometry().width()/(axisY()->ticksCount()-1));
317 322 }
318 323
319 324 void QChart::setBackgroundVisible(bool visible)
320 325 {
321 326 d_ptr->createChartBackgroundItem();
322 327 d_ptr->m_backgroundItem->setVisible(visible);
323 328 }
324 329
325 330 bool QChart::isBackgroundVisible() const
326 331 {
327 332 if (!d_ptr->m_backgroundItem) return false;
328 333 return d_ptr->m_backgroundItem->isVisible();
329 334 }
330 335
331 336 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
332 337
333 338 QChartPrivate::QChartPrivate(QChart *parent):
334 339 q_ptr(parent),
335 340 m_backgroundItem(0),
336 341 m_titleItem(0),
337 342 m_legend(0),
338 343 m_dataset(0),
339 m_presenter(0)
344 m_presenter(0),
345 m_padding(QRectF(50,50,50,50))
340 346 {
341 347
342 348 }
343 349
344 350 QChartPrivate::~QChartPrivate()
345 351 {
346 352
347 353 }
348 354
349 355 void QChartPrivate::createChartBackgroundItem()
350 356 {
351 357 if (!m_backgroundItem) {
352 358 m_backgroundItem = new ChartBackground(q_ptr);
353 359 m_backgroundItem->setPen(Qt::NoPen);
354 360 m_backgroundItem->setZValue(ChartPresenter::BackgroundZValue);
355 361 }
356 362 }
357 363
358 364 void QChartPrivate::createChartTitleItem()
359 365 {
360 366 if (!m_titleItem) {
361 367 m_titleItem = new QGraphicsSimpleTextItem(q_ptr);
362 368 m_titleItem->setZValue(ChartPresenter::BackgroundZValue);
363 369 }
364 370 }
365 371
366 372 void QChartPrivate::updateLegendLayout()
367 373 {
368 int padding = m_presenter->padding();
369 QRectF plotRect = m_rect.adjusted(padding,padding,-padding,-padding);
374 //int legendPadding = m_chart->legend()->padding();
375 int legendPadding = 30;
376 QRectF rect = m_rect;
377
378 if ((m_legend->attachedToChart()) && (m_legend->isVisible())) {
379
380 // Reserve some space for legend
381 switch (m_legend->alignment()) {
382 case QLegend::AlignmentTop: {
383 rect.adjust(m_padding.left(),
384 m_padding.top() + legendPadding,
385 -m_padding.right(),
386 -m_padding.bottom());
387 break;
388 }
389 case QLegend::AlignmentBottom: {
390 rect.adjust(m_padding.left(),
391 m_padding.top(),
392 -m_padding.right(),
393 -m_padding.bottom() - legendPadding);
394 break;
395 }
396 case QLegend::AlignmentLeft: {
397 rect.adjust(m_padding.left() + legendPadding,
398 m_padding.top(),
399 -m_padding.right(),
400 -m_padding.bottom());
401 break;
402 }
403 case QLegend::AlignmentRight: {
404 rect.adjust(m_padding.left(),
405 m_padding.top(),
406 -m_padding.right() - legendPadding,
407 -m_padding.bottom());
408 break;
409 }
410 default: {
411 rect.adjust(m_padding.left(),
412 m_padding.top(),
413 -m_padding.right(),
414 -m_padding.bottom());
415 break;
416 }
417 }
418 } else {
419
420 rect.adjust(m_padding.left(),
421 m_padding.top(),
422 -m_padding.right(),
423 -m_padding.bottom());
424 }
425
426 QRectF plotRect = m_rect.adjusted(m_padding.left()
427 ,m_padding.top()
428 ,-m_padding.right()
429 ,-m_padding.bottom());
370 430 QRectF legendRect;
371 431
432 int padding = 0; // TODO: fix this
372 433 switch (m_legend->alignment())
373 434 {
374 435 case QLegend::AlignmentTop: {
375 436 legendRect = m_rect.adjusted(0,padding,0,-padding - plotRect.height());
376 437 break;
377 438 }
378 439 case QLegend::AlignmentBottom: {
379 440 legendRect = m_rect.adjusted(padding,padding + plotRect.height(),-padding,0);
380 441 break;
381 442 }
382 443 case QLegend::AlignmentLeft: {
383 444 legendRect = m_rect.adjusted(0,padding,-padding - plotRect.width(),-padding);
384 445 break;
385 446 }
386 447 case QLegend::AlignmentRight: {
387 448 legendRect = m_rect.adjusted(padding + plotRect.width(),padding,0,-padding);
388 449 break;
389 450 }
390 451 default: {
391 452 legendRect = plotRect;
392 453 break;
393 454 }
394 455 }
395 456
396 457 m_legend->setMaximumSize(legendRect.size());
397 458
398 459 qreal width = legendRect.width() - m_legend->size().width();
399 460 qreal height = legendRect.height() - m_legend->size().height();
400 461
401 462 QPointF pos = legendRect.topLeft();
402 463 if (width > 0) {
403 464 pos.setX(pos.x() + width/2);
404 465 }
405 466 if (height > 0) {
406 467 pos.setY(pos.y() + height/2);
407 468 }
408 469
409 qDebug() << "lenged topleft:" << pos;
410 470 m_legend->setPos(pos);
411 471 }
412 472
413 473 void QChartPrivate::updateLayout()
414 474 {
415 475 if (!m_rect.isValid()) return;
416 476
417 int padding = m_presenter->padding();
477 int padding = m_padding.top();
418 478 int backgroundPadding = m_presenter->backgroundPadding();
419 479
420 480 // recalculate title position
421 481 if (m_titleItem) {
422 482 QPointF center = m_rect.center() -m_titleItem->boundingRect().center();
423 483 m_titleItem->setPos(center.x(),m_rect.top()/2 + padding/2);
424 484 }
425 485
426 486 //recalculate background gradient
427 487 if (m_backgroundItem) {
428 488 m_backgroundItem->setRect(m_rect.adjusted(backgroundPadding,backgroundPadding, -backgroundPadding, -backgroundPadding));
429 489 }
430 490
431 491 // recalculate legend position
432 492 if (m_legend) {
433 493 if ((m_legend->attachedToChart()) && (m_legend->parentObject() == q_ptr)) {
434 494 updateLegendLayout();
435 495 }
436 496 }
437 497 }
438 498
439 499 #include "moc_qchart.cpp"
440 500
441 501 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,116 +1,118
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #ifndef QCHART_H
22 22 #define QCHART_H
23 23
24 24 #include <QSeries>
25 25 #include <QGraphicsWidget>
26 26
27 27 class QGraphicsSceneResizeEvent;
28 28
29 29 QTCOMMERCIALCHART_BEGIN_NAMESPACE
30 30
31 31 class QSeries;
32 32 class QChartAxis;
33 33 class QLegend;
34 34 struct QChartPrivate;
35 35
36 36 class QTCOMMERCIALCHART_EXPORT QChart : public QGraphicsWidget
37 37 {
38 38 Q_OBJECT
39 39 public:
40 40 enum ChartTheme {
41 41 ChartThemeDefault,
42 42 ChartThemeLight,
43 43 ChartThemeBlueCerulean,
44 44 ChartThemeDark,
45 45 ChartThemeBrownSand,
46 46 ChartThemeBlueNcs,
47 47 ChartThemeHighContrast,
48 48 ChartThemeBlueIcy,
49 49 ChartThemeCount
50 50 };
51 51
52 52 enum AnimationOption {
53 53 NoAnimation = 0x0,
54 54 GridAxisAnimations = 0x1,
55 55 SeriesAnimations =0x2,
56 56 AllAnimations = 0x3
57 57 };
58 58
59 59 Q_DECLARE_FLAGS(AnimationOptions, AnimationOption)
60 60
61 61 public:
62 62 explicit QChart(QGraphicsItem *parent = 0, Qt::WindowFlags wFlags = 0);
63 63 ~QChart();
64 64
65 65 void addSeries(QSeries *series, QChartAxis *axisY = 0);
66 66 void removeSeries(QSeries *series);
67 67 void removeAllSeries();
68 68
69 69 void setTheme(QChart::ChartTheme theme);
70 70 QChart::ChartTheme theme() const;
71 71
72 72 void setTitle(const QString& title);
73 73 QString title() const;
74 74 void setTitleFont(const QFont& font);
75 75 QFont titleFont() const;
76 76 void setTitleBrush(const QBrush &brush);
77 77 QBrush titleBrush() const;
78 78 void setBackgroundBrush(const QBrush &brush);
79 79 QBrush backgroundBrush() const;
80 80 void setBackgroundPen(const QPen &pen);
81 81 QPen backgroundPen() const;
82 82
83 83 void setBackgroundVisible(bool visible);
84 84 bool isBackgroundVisible() const;
85 85
86 86 void setAnimationOptions(AnimationOptions options);
87 87 AnimationOptions animationOptions() const;
88 88
89 89 void zoomIn();
90 90 void zoomIn(const QRectF &rect);
91 91 void zoomOut();
92 92 void scrollLeft();
93 93 void scrollRight();
94 94 void scrollUp();
95 95 void scrollDown();
96 96
97 97 QChartAxis* axisX() const;
98 98 QChartAxis* axisY() const;
99 99
100 100 QLegend* legend() const;
101 101
102 QRectF padding() const;
103
102 104 protected:
103 105 void resizeEvent(QGraphicsSceneResizeEvent *event);
104 106
105 107 protected:
106 108 QScopedPointer<QChartPrivate> d_ptr;
107 109 friend class QChartView;
108 110 friend class QLegend;
109 111 Q_DISABLE_COPY(QChart)
110 112 };
111 113
112 114 QTCOMMERCIALCHART_END_NAMESPACE
113 115
114 116 Q_DECLARE_OPERATORS_FOR_FLAGS(QTCOMMERCIALCHART_NAMESPACE::QChart::AnimationOptions)
115 117
116 118 #endif
@@ -1,63 +1,64
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 // W A R N I N G
22 22 // -------------
23 23 //
24 24 // This file is not part of the QtCommercial Chart API. It exists purely as an
25 25 // implementation detail. This header file may change from version to
26 26 // version without notice, or even be removed.
27 27 //
28 28 // We mean it.
29 29
30 30 #ifndef QCHART_P_H
31 31 #define QCHART_P_H
32 32
33 33 #include "qchartaxis.h"
34 34 #include "qlegend.h"
35 35 #include "chartpresenter_p.h"
36 36 #include "chartdataset_p.h"
37 37 #include "chartbackground_p.h"
38 38
39 39 QTCOMMERCIALCHART_BEGIN_NAMESPACE
40 40
41 41 class QChart;
42 42
43 43 struct QChartPrivate
44 44 {
45 45 QChartPrivate(QChart *parent);
46 46 ~QChartPrivate();
47 47
48 48 void createChartBackgroundItem();
49 49 void createChartTitleItem();
50 50 void updateLayout();
51 51 void updateLegendLayout();
52 52
53 53 QChart *q_ptr;
54 54 ChartBackground* m_backgroundItem;
55 55 QGraphicsSimpleTextItem* m_titleItem;
56 56 QRectF m_rect;
57 57 QLegend* m_legend;
58 58 ChartDataSet *m_dataset;
59 59 ChartPresenter *m_presenter;
60 QRectF m_padding;
60 61 };
61 62
62 63 QTCOMMERCIALCHART_END_NAMESPACE
63 64 #endif
@@ -1,233 +1,233
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "qchartview.h"
22 22 #include "qchart_p.h"
23 23 #include "qchartview_p.h"
24 24 #include <QGraphicsScene>
25 25 #include <QRubberBand>
26 26
27 27
28 28 /*!
29 29 \enum QChartView::RubberBandPolicy
30 30
31 31 This enum describes the different types of rubber bands that can be used for zoom rect selection
32 32
33 33 \value NoRubberBand
34 34 \value VerticalRubberBand
35 35 \value HorizonalRubberBand
36 36 \value RectangleRubberBand
37 37 */
38 38
39 39 /*!
40 40 \class QChartView
41 41 \brief Standalone charting widget.
42 42
43 43 QChartView is a standalone widget that can display charts. It does not require separate
44 44 QGraphicsScene to work. It manages the graphical representation of different types of
45 45 QChartSeries and other chart related objects like QChartAxis and QChartLegend. If you want to
46 46 display a chart in your existing QGraphicsScene, you can use the QChart class instead.
47 47
48 48 \sa QChart
49 49 */
50 50
51 51 QTCOMMERCIALCHART_BEGIN_NAMESPACE
52 52
53 53 /*!
54 54 Constructs a chartView object which is a child of a\a parent.
55 55 */
56 56 QChartView::QChartView(QChart *chart,QWidget *parent) :
57 57 QGraphicsView(parent),
58 58 d_ptr(new QChartViewPrivate())
59 59 {
60 60 d_ptr->m_scene = new QGraphicsScene(this);
61 61 d_ptr->m_chart = chart;
62 62 d_ptr->m_presenter = chart->d_ptr->m_presenter;
63 63 setFrameShape(QFrame::NoFrame);
64 64 setBackgroundRole(QPalette::Window);
65 65 setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
66 66 setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
67 67 setScene(d_ptr->m_scene);
68 68 d_ptr->m_scene->addItem(chart);
69 69 setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
70 70 }
71 71
72 72
73 73 /*!
74 74 Destroys the object and it's children, like QChartSeries and QChartAxis object added to it.
75 75 */
76 76 QChartView::~QChartView()
77 77 {
78 78 }
79 79
80 80 QChart* QChartView::chart() const
81 81 {
82 82 return d_ptr->m_chart;
83 83 }
84 84
85 85 /*!
86 86 Sets the RubberBandPlicy to \a policy. Selected policy determines the way zooming is performed.
87 87 */
88 88 void QChartView::setRubberBand(const RubberBands& rubberBand)
89 89 {
90 90 d_ptr->m_rubberBandFlags=rubberBand;
91 91
92 92 if (!d_ptr->m_rubberBandFlags) {
93 93 delete d_ptr->m_rubberBand;
94 94 d_ptr->m_rubberBand=0;
95 95 return;
96 96 }
97 97
98 98 if (!d_ptr->m_rubberBand) {
99 99 d_ptr->m_rubberBand = new QRubberBand(QRubberBand::Rectangle, this);
100 100 d_ptr->m_rubberBand->setEnabled(true);
101 101 }
102 102 }
103 103
104 104 /*!
105 105 Returns the RubberBandPolicy that is currently being used by the widget.
106 106 */
107 107 QChartView::RubberBands QChartView::rubberBand() const
108 108 {
109 109 return d_ptr->m_rubberBandFlags;
110 110 }
111 111
112 112 /*!
113 113 If Left mouse button is pressed and the RubberBandPolicy is enabled the \a event is accepted and the rubber band is displayed on the screen allowing the user to select the zoom area.
114 114 If different mouse button is pressed and/or the RubberBandPolicy is disabled then the \a event is passed to QGraphicsView::mousePressEvent() implementation.
115 115 */
116 116 void QChartView::mousePressEvent(QMouseEvent *event)
117 117 {
118 118 if(d_ptr->m_rubberBand && d_ptr->m_rubberBand->isEnabled() && event->button() == Qt::LeftButton) {
119 119
120 int padding = d_ptr->m_presenter->padding();
120 int padding = d_ptr->m_chart->padding().top();
121 121 QRect rect(padding, padding, width() - 2 * padding, height() - 2 * padding);
122 122
123 123 if (rect.contains(event->pos())) {
124 124 d_ptr->m_rubberBandOrigin = event->pos();
125 125 d_ptr->m_rubberBand->setGeometry(QRect(d_ptr->m_rubberBandOrigin, QSize()));
126 126 d_ptr->m_rubberBand->show();
127 127 event->accept();
128 128 }
129 129 }
130 130 else {
131 131 QGraphicsView::mousePressEvent(event);
132 132 }
133 133 }
134 134
135 135 /*!
136 136 If RubberBand rectange specification has been initiated in pressEvent then \a event data is used to update RubberBand geometry.
137 137 In other case the defualt QGraphicsView::mouseMoveEvent implementation is called.
138 138 */
139 139 void QChartView::mouseMoveEvent(QMouseEvent *event)
140 140 {
141 141 if(d_ptr->m_rubberBand && d_ptr->m_rubberBand->isVisible()) {
142 int padding = d_ptr->m_presenter->padding();
142 int padding = d_ptr->m_chart->padding().top();
143 143 QRect rect(padding, padding, width() - 2 * padding, height() - 2 * padding);
144 144 int width = event->pos().x() - d_ptr->m_rubberBandOrigin.x();
145 145 int height = event->pos().y() - d_ptr->m_rubberBandOrigin.y();
146 146 if (!d_ptr->m_rubberBandFlags.testFlag(VerticalRubberBand)) {
147 147 d_ptr->m_rubberBandOrigin.setY(rect.top());
148 148 height = rect.height();
149 149 }
150 150 if (!d_ptr->m_rubberBandFlags.testFlag(HorizonalRubberBand)) {
151 151 d_ptr->m_rubberBandOrigin.setX(rect.left());
152 152 width= rect.width();
153 153 }
154 154 d_ptr->m_rubberBand->setGeometry(QRect(d_ptr->m_rubberBandOrigin.x(),d_ptr->m_rubberBandOrigin.y(), width,height).normalized());
155 155 }
156 156 else {
157 157 QGraphicsView::mouseMoveEvent(event);
158 158 }
159 159 }
160 160
161 161 /*!
162 162 If left mouse button is release and RubberBand is enabled then \a event is accepted and the view is zoomed in to rect specified by RubberBand
163 163 If it is the right mouse button \a event then RubberBand is dissmissed and zoom is canceled.
164 164 */
165 165 void QChartView::mouseReleaseEvent(QMouseEvent *event)
166 166 {
167 167 if(d_ptr->m_rubberBand) {
168 168 if (event->button() == Qt::LeftButton && d_ptr->m_rubberBand->isVisible()) {
169 169 d_ptr->m_rubberBand->hide();
170 170 QRect rect = d_ptr->m_rubberBand->geometry();
171 171 d_ptr->m_chart->zoomIn(rect);
172 172 event->accept();
173 173 }
174 174
175 175 if(event->button()==Qt::RightButton){
176 176 d_ptr->m_chart->zoomOut();
177 177 event->accept();
178 178 }
179 179 }
180 180 else {
181 181 QGraphicsView::mouseReleaseEvent(event);
182 182 }
183 183 }
184 184
185 185 /*!
186 186 Pressing + and - keys performs zoomIn() and zoomOut() respectivly.
187 187 In other \a event is passed to the QGraphicsView::keyPressEvent() implementation
188 188 */
189 189 void QChartView::keyPressEvent(QKeyEvent *event)
190 190 {
191 191 switch (event->key()) {
192 192 case Qt::Key_Plus:
193 193 d_ptr->m_chart->zoomIn();
194 194 break;
195 195 case Qt::Key_Minus:
196 196 d_ptr->m_chart->zoomOut();
197 197 break;
198 198 default:
199 199 QGraphicsView::keyPressEvent(event);
200 200 break;
201 201 }
202 202 }
203 203
204 204 /*!
205 205 Resizes and updates the chart area using the \a event data
206 206 */
207 207 void QChartView::resizeEvent(QResizeEvent *event)
208 208 {
209 209 QGraphicsView::resizeEvent(event);
210 210 d_ptr->m_chart->resize(size());
211 211 setSceneRect(d_ptr->m_chart->geometry());
212 212 }
213 213
214 214 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
215 215
216 216 QChartViewPrivate::QChartViewPrivate():
217 217 m_scene(0),
218 218 m_chart(0),
219 219 m_presenter(0),
220 220 m_rubberBand(0),
221 221 m_rubberBandFlags(QChartView::NoRubberBand)
222 222 {
223 223
224 224 }
225 225
226 226 QChartViewPrivate::~QChartViewPrivate()
227 227 {
228 228
229 229 }
230 230
231 231 #include "moc_qchartview.cpp"
232 232
233 233 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,720 +1,724
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "qlegend.h"
22 22 #include "qchart_p.h"
23 23 #include "qseries.h"
24 24 #include "legendmarker_p.h"
25 25 #include "legendscrollbutton_p.h"
26 26 #include "qxyseries.h"
27 27 #include "qlineseries.h"
28 28 #include "qareaseries.h"
29 29 #include "qscatterseries.h"
30 30 #include "qsplineseries.h"
31 31 #include "qbarseries.h"
32 32 #include "qstackedbarseries.h"
33 33 #include "qpercentbarseries.h"
34 34 #include "qbarset.h"
35 35 #include "qpieseries.h"
36 36 #include "qpieslice.h"
37 37 #include "chartpresenter_p.h"
38 38 #include <QPainter>
39 39 #include <QPen>
40 40
41 41 #include <QGraphicsSceneEvent>
42 42
43 43 QTCOMMERCIALCHART_BEGIN_NAMESPACE
44 44
45 45 /*!
46 46 \class QLegend
47 47 \brief part of QtCommercial chart API.
48 48
49 49 QLegend is a graphical object, whics displays legend of the chart. Legend state is updated by QChart, when
50 50 series have been changed. By default, legend is drawn by QChart, but user can set a new parent to legend and
51 51 handle the drawing manually.
52 52 User isn't supposed to create or delete legend objects, but can reference it via QChart class.
53 53
54 54 \mainclass
55 55
56 56 \sa QChart, QSeries
57 57 */
58 58
59 59 /*!
60 60 \enum QLegend::Layout
61 61
62 62 This enum describes the possible position for legend inside chart.
63 63
64 64 \value LayoutTop
65 65 \value LayoutBottom
66 66 \value LayoutLeft
67 67 \value LayoutRight
68 68 */
69 69
70 70
71 71 /*!
72 72 \fn void QLegend::clicked(QSeries* series, Qt::MouseButton button)
73 73 \brief Notifies when series has been clicked on legend \a series \a button
74 74 */
75 75
76 76 /*!
77 77 \fn void QLegend::clicked(QBarSet* barset, Qt::MouseButton button)
78 78 \brief Notifies when barset has been clicked on legend \a barset \a button
79 79 */
80 80
81 81 /*!
82 82 \fn void QLegend::clicked(QPieSlice* slice, Qt::MouseButton button)
83 83 \brief Notifies when pie slice has been clicked on legend \a slice \a button
84 84 */
85 85
86 86 /*!
87 87 Constructs the legend object and sets the parent to \a parent
88 88 */
89 89 QLegend::QLegend(QChart *chart):QGraphicsWidget(chart),
90 90 m_margin(5),
91 91 m_pos(0,0),
92 92 m_minimumSize(50,20), // TODO: magic numbers
93 93 m_maximumSize(150,100),
94 94 m_size(m_minimumSize),
95 95 m_brush(Qt::darkGray), // TODO: default should come from theme
96 96 m_alignment(QLegend::AlignmentTop),
97 97 mFirstMarker(0),
98 m_attachedToChart(true)
98 m_attachedToChart(true),
99 m_chart(chart)
99 100 {
100 101 m_scrollButtonLeft = new LegendScrollButton(LegendScrollButton::ScrollButtonIdLeft, this);
101 102 m_scrollButtonRight = new LegendScrollButton(LegendScrollButton::ScrollButtonIdRight, this);
102 103 m_scrollButtonUp = new LegendScrollButton(LegendScrollButton::ScrollButtonIdUp, this);
103 104 m_scrollButtonDown = new LegendScrollButton(LegendScrollButton::ScrollButtonIdDown, this);
104 105 setZValue(ChartPresenter::LegendZValue);
105 106 }
106 107
107 108 /*!
108 109 Paints the legend to given \a painter. Paremeters \a option and \a widget arent used.
109 110 */
110 111 void QLegend::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
111 112 {
112 113 Q_UNUSED(option)
113 114 Q_UNUSED(widget)
114 115
115 116 painter->setOpacity(opacity());
116 117 painter->setPen(m_pen);
117 118 painter->setBrush(m_brush);
118 119 // painter->drawRect(boundingRect());
119 120 }
120 121
121 122 /*!
122 123 Bounding rect of legend.
123 124 */
124 125 QRectF QLegend::boundingRect() const
125 126 {
126 127 return QRectF(m_pos,m_size);
127 128 }
128 129
129 130 /*!
130 131 Sets the \a brush of legend. Brush affects the background of legend.
131 132 */
132 133 void QLegend::setBrush(const QBrush &brush)
133 134 {
134 135 if (m_brush != brush) {
135 136 m_brush = brush;
136 137 update();
137 138 }
138 139 }
139 140
140 141 /*!
141 142 Returns the brush used by legend.
142 143 */
143 144 QBrush QLegend::brush() const
144 145 {
145 146 return m_brush;
146 147 }
147 148
148 149 /*!
149 150 Sets the \a pen of legend. Pen affects the legend borders.
150 151 */
151 152 void QLegend::setPen(const QPen &pen)
152 153 {
153 154 if (m_pen != pen) {
154 155 m_pen = pen;
155 156 update();
156 157 }
157 158 }
158 159
159 160 /*!
160 161 Returns the pen used by legend
161 162 */
162 163
163 164 QPen QLegend::pen() const
164 165 {
165 166 return m_pen;
166 167 }
167 168
168 169 /*!
169 170 Sets the \a preferred layout for legend. Legend tries to paint itself on the defined position in chart.
170 171 \sa QLegend::Layout
171 172 */
172 void QLegend::setAlignmnent(QLegend::Alignment alignment)
173 void QLegend::setAlignmnent(QLegend::Alignments alignment)
173 174 {
175 // if (!m_attachedToChart) {
174 176 m_alignment = alignment;
175 177 updateLayout();
178 m_chart->resize(m_chart->size());
179 // }
176 180 }
177 181
178 182 /*!
179 183 Returns the preferred layout for legend
180 184 */
181 QLegend::Alignment QLegend::alignment() const
185 QLegend::Alignments QLegend::alignment() const
182 186 {
183 187 return m_alignment;
184 188 }
185 189
186 190 /*!
187 191 Returns the maximum size of legend.
188 192 */
189 193 QSizeF QLegend::maximumSize() const
190 194 {
191 195 return m_maximumSize;
192 196 }
193 197
194 198 /*!
195 199 Sets the maximum \a size for legend. The legend can't grow bigger than this size. If there are
196 200 more series than legend can fit to this size, scroll buttons are displayed.
197 201 */
198 202 void QLegend::setMaximumSize(const QSizeF size)
199 203 {
200 204 m_maximumSize = size;
201 205 updateLayout();
202 206 }
203 207
204 208 /*!
205 209 Returns the current size of legend.
206 210 */
207 211 QSizeF QLegend::size() const
208 212 {
209 213 return m_size;
210 214 }
211 215
212 216 /*!
213 217 Sets the \a size of legend. If size is bigger than maximum size of legend, the legend is resized to the maximum size.
214 218 \sa setMmaximumSize()
215 219 */
216 220 void QLegend::setSize(const QSizeF size)
217 221 {
218 222 m_size = size;
219 223 if (m_size.width() > m_maximumSize.width()) {
220 224 m_size.setWidth(m_maximumSize.width());
221 225 }
222 226 if (m_size.height() > m_maximumSize.height()) {
223 227 m_size.setHeight(m_maximumSize.height());
224 228 }
225 229 }
226 230
227 231 /*!
228 232 Sets position of legend to \a pos
229 233 */
230 234 void QLegend::setPos(const QPointF &pos)
231 235 {
232 236 m_pos = pos;
233 237 updateLayout();
234 238 }
235 239
236 240 /*!
237 241 \internal \a series \a domain Should be called when series is added to chart.
238 242 */
239 243 void QLegend::handleSeriesAdded(QSeries *series, Domain *domain)
240 244 {
241 245 Q_UNUSED(domain)
242 246
243 247 switch (series->type())
244 248 {
245 249 case QSeries::SeriesTypeLine: {
246 250 QLineSeries *lineSeries = static_cast<QLineSeries *>(series);
247 251 appendMarkers(lineSeries);
248 252 break;
249 253 }
250 254 case QSeries::SeriesTypeArea: {
251 255 QAreaSeries *areaSeries = static_cast<QAreaSeries *>(series);
252 256 appendMarkers(areaSeries);
253 257 break;
254 258 }
255 259 case QSeries::SeriesTypeBar: {
256 260 QBarSeries *barSeries = static_cast<QBarSeries *>(series);
257 261 appendMarkers(barSeries);
258 262 break;
259 263 }
260 264 case QSeries::SeriesTypeStackedBar: {
261 265 QStackedBarSeries *stackedBarSeries = static_cast<QStackedBarSeries *>(series);
262 266 appendMarkers(stackedBarSeries);
263 267 break;
264 268 }
265 269 case QSeries::SeriesTypePercentBar: {
266 270 QPercentBarSeries *percentBarSeries = static_cast<QPercentBarSeries *>(series);
267 271 appendMarkers(percentBarSeries);
268 272 break;
269 273 }
270 274 case QSeries::SeriesTypeScatter: {
271 275 QScatterSeries *scatterSeries = static_cast<QScatterSeries *>(series);
272 276 appendMarkers(scatterSeries);
273 277 break;
274 278 }
275 279 case QSeries::SeriesTypePie: {
276 280 QPieSeries *pieSeries = static_cast<QPieSeries *>(series);
277 281 appendMarkers(pieSeries);
278 282 connect(pieSeries,SIGNAL(added(QList<QPieSlice*>)),this,SLOT(handleAdded(QList<QPieSlice*>)));
279 283 break;
280 284 }
281 285 case QSeries::SeriesTypeSpline: {
282 286 QSplineSeries *splineSeries = static_cast<QSplineSeries *>(series);
283 287 appendMarkers(splineSeries);
284 288 break;
285 289 }
286 290 default: {
287 291 qWarning()<< "QLegend::handleSeriesAdded" << series->type() << "unknown series type.";
288 292 break;
289 293 }
290 294 }
291 295
292 296 updateLayout();
293 297 }
294 298
295 299 /*!
296 300 \internal \a series Should be called when series is removed from chart.
297 301 */
298 302 void QLegend::handleSeriesRemoved(QSeries *series)
299 303 {
300 304 switch (series->type())
301 305 {
302 306 case QSeries::SeriesTypeArea: {
303 307 QAreaSeries *areaSeries = static_cast<QAreaSeries *>(series);
304 308 deleteMarkers(areaSeries);
305 309 break;
306 310 }
307 311 case QSeries::SeriesTypePie: {
308 312 QPieSeries *pieSeries = static_cast<QPieSeries *>(series);
309 313 disconnect(pieSeries, SIGNAL(added(QList<QPieSlice *>)), this, SLOT(handleAdded(QList<QPieSlice *>)));
310 314 deleteMarkers(series);
311 315 break;
312 316 }
313 317 default: {
314 318 // All other types
315 319 deleteMarkers(series);
316 320 break;
317 321 }
318 322 }
319 323
320 324 updateLayout();
321 325 }
322 326
323 327 /*!
324 328 \internal \a slices Should be called when slices are added to pie chart.
325 329 */
326 330 void QLegend::handleAdded(QList<QPieSlice *> slices)
327 331 {
328 332 QPieSeries* series = static_cast<QPieSeries *> (sender());
329 333 foreach(QPieSlice* s, slices) {
330 334 LegendMarker* marker = new LegendMarker(series, s, this);
331 335 marker->setName(s->label());
332 336 marker->setBrush(s->brush());
333 337 connect(marker, SIGNAL(clicked(QPieSlice*,Qt::MouseButton)),
334 338 this, SIGNAL(clicked(QPieSlice*,Qt::MouseButton)));
335 339 connect(s, SIGNAL(changed()), marker, SLOT(changed()));
336 340 connect(s, SIGNAL(destroyed()), marker, SLOT(deleteLater()));
337 341 connect(marker, SIGNAL(destroyed()), this, SLOT(handleMarkerDestroyed()));
338 342 m_markers.append(marker);
339 343 childItems().append(marker);
340 344 }
341 345 updateLayout();
342 346 }
343 347
344 348 /*!
345 349 \internal \a slices Should be called when slices are removed from pie chart. Currently unused,
346 350 because removed slices are also deleted and we listen destroyed signal
347 351 */
348 352 void QLegend::handleRemoved(QList<QPieSlice *> slices)
349 353 {
350 354 Q_UNUSED(slices)
351 355 }
352 356
353 357
354 358 /*!
355 359 \internal Notifies legend that some marker has been removed. Sent by legend markers when destroyed
356 360 */
357 361 void QLegend::handleMarkerDestroyed()
358 362 {
359 363 LegendMarker* m = static_cast<LegendMarker *> (sender());
360 364 m_markers.removeOne(m);
361 365 updateLayout();
362 366 }
363 367
364 368 /*!
365 369 \internal \a event Handles clicked signals from scroll buttons
366 370 */
367 371 void QLegend::scrollButtonClicked(LegendScrollButton *scrollButton)
368 372 {
369 373 Q_ASSERT(scrollButton);
370 374
371 375 switch (scrollButton->id()) {
372 376 case LegendScrollButton::ScrollButtonIdLeft:
373 377 case LegendScrollButton::ScrollButtonIdUp: {
374 378 // Lower limit is same in these cases
375 379 mFirstMarker--;
376 380 checkFirstMarkerBounds();
377 381 break;
378 382 }
379 383 case LegendScrollButton::ScrollButtonIdRight:
380 384 case LegendScrollButton::ScrollButtonIdDown: {
381 385 mFirstMarker++;
382 386 checkFirstMarkerBounds();
383 387 break;
384 388 }
385 389 default: {
386 390 break;
387 391 }
388 392 }
389 393 updateLayout();
390 394 }
391 395
392 396 /*!
393 397 Detaches the legend from chart. Chart won't change layout of the legend.
394 398 */
395 399 void QLegend::detachFromChart()
396 400 {
397 401 m_attachedToChart = false;
398 402 }
399 403
400 404 /*!
401 405 Attaches the legend to chart. Chart may change layout of the legend.
402 406 */
403 407 void QLegend::attachToChart()
404 408 {
405 409 m_attachedToChart = true;
406 410 }
407 411
408 412 /*!
409 413 Returns true, if legend is attached to chart.
410 414 */
411 415 bool QLegend::attachedToChart()
412 416 {
413 417 return m_attachedToChart;
414 418 }
415 419
416 420 /*!
417 421 \internal Helper function. Appends markers from \a series to legend.
418 422 */
419 423 void QLegend::appendMarkers(QAreaSeries* series)
420 424 {
421 425 LegendMarker* marker = new LegendMarker(series,this);
422 426 connect(marker, SIGNAL(clicked(QSeries *, Qt::MouseButton)), this, SIGNAL(clicked(QSeries *, Qt::MouseButton)));
423 427 connect(marker, SIGNAL(destroyed()), this, SLOT(handleMarkerDestroyed()));
424 428 connect(series,SIGNAL(updated()),marker,SLOT(changed()));
425 429 marker->changed();
426 430 m_markers.append(marker);
427 431 childItems().append(marker);
428 432 }
429 433
430 434 /*!
431 435 \internal Helper function. Appends markers from \a series to legend.
432 436 */
433 437 void QLegend::appendMarkers(QXYSeries* series)
434 438 {
435 439 LegendMarker* marker = new LegendMarker(series,this);
436 440 connect(marker, SIGNAL(clicked(QSeries *, Qt::MouseButton)), this, SIGNAL(clicked(QSeries *, Qt::MouseButton)));
437 441 connect(marker, SIGNAL(destroyed()), this, SLOT(handleMarkerDestroyed()));
438 442 connect(series,SIGNAL(updated()),marker,SLOT(changed()));
439 443 marker->changed();
440 444 m_markers.append(marker);
441 445 childItems().append(marker);
442 446 }
443 447
444 448 /*!
445 449 \internal Helper function. Appends markers from \a series to legend.
446 450 */
447 451 void QLegend::appendMarkers(QBarSeries *series)
448 452 {
449 453 foreach(QBarSet* set, series->barSets()) {
450 454 LegendMarker* marker = new LegendMarker(series, set, this);
451 455 connect(marker, SIGNAL(clicked(QBarSet *, Qt::MouseButton)),
452 456 this, SIGNAL(clicked(QBarSet *, Qt::MouseButton)));
453 457 connect(set, SIGNAL(valueChanged()), marker, SLOT(changed()));
454 458 connect(marker, SIGNAL(destroyed()), this, SLOT(handleMarkerDestroyed()));
455 459 marker->changed();
456 460 m_markers.append(marker);
457 461 childItems().append(marker);
458 462 }
459 463 }
460 464
461 465 /*!
462 466 \internal Helper function. Appends markers from \a series to legend.
463 467 */
464 468 void QLegend::appendMarkers(QPieSeries *series)
465 469 {
466 470 foreach(QPieSlice* slice, series->slices()) {
467 471 LegendMarker* marker = new LegendMarker(series, slice, this);
468 472 connect(marker, SIGNAL(clicked(QPieSlice *, Qt::MouseButton)),
469 473 this, SIGNAL(clicked(QPieSlice *, Qt::MouseButton)));
470 474 connect(slice, SIGNAL(changed()), marker, SLOT(changed()));
471 475 connect(slice, SIGNAL(destroyed()), marker, SLOT(deleteLater()));
472 476 connect(marker, SIGNAL(destroyed()), this, SLOT(handleMarkerDestroyed()));
473 477 marker->changed();
474 478 m_markers.append(marker);
475 479 childItems().append(marker);
476 480 }
477 481 }
478 482
479 483 /*!
480 484 \internal Deletes all markers that are created from \a series
481 485 */
482 486 void QLegend::deleteMarkers(QSeries *series)
483 487 {
484 488 // Search all markers that belong to given series and delete them.
485 489 foreach (LegendMarker *m, m_markers) {
486 490 if (m->series() == series) {
487 491 m_markers.removeOne(m);
488 492 delete m;
489 493 }
490 494 }
491 495 }
492 496
493 497 /*!
494 498 \internal Updates layout of legend. Tries to fit as many markers as possible up to the maximum size of legend.
495 499 If items don't fit, sets the visibility of scroll buttons accordingly.
496 500 Causes legend to be resized.
497 501 */
498 502 void QLegend::updateLayout()
499 503 {
500 504 // Calculate layout for markers and text
501 505 if (m_markers.count() <= 0) {
502 506 // Nothing to do
503 507 return;
504 508 }
505 509
506 510 // Find out widest item.
507 511 QSizeF markerMaxSize = maximumMarkerSize();
508 512 checkFirstMarkerBounds();
509 513
510 514 // Use max height as scroll button size
511 515 rescaleScrollButtons(QSize(markerMaxSize.height() ,markerMaxSize.height()));
512 516
513 517 qreal totalWidth = 0;
514 518 qreal totalHeight = 0;
515 519 switch (m_alignment)
516 520 {
517 521 // Both cases organise items horizontally
518 522 case QLegend::AlignmentBottom:
519 523 case QLegend::AlignmentTop: {
520 524
521 525 qreal xStep = markerMaxSize.width();
522 526 qreal x = m_pos.x() + m_margin;
523 527 qreal y = m_pos.y() + m_margin;
524 528 int column = 0;
525 529 int maxColumns = 1;
526 530 qreal scrollButtonWidth = 0;
527 531
528 532 // Set correct visibility for scroll scrollbuttons
529 533 if (scrollButtonsVisible()) {
530 534 m_scrollButtonLeft->setVisible(true);
531 535 m_scrollButtonRight->setVisible(true);
532 536 // scrollbuttons visible, so add their width to total width
533 537 totalWidth += (m_scrollButtonLeft->boundingRect().width() + m_margin) * 2;
534 538 scrollButtonWidth = m_scrollButtonLeft->boundingRect().width() + m_margin;
535 539 // start position changes by scrollbutton width
536 540 x += scrollButtonWidth;
537 541 } else {
538 542 m_scrollButtonLeft->setVisible(false);
539 543 m_scrollButtonRight->setVisible(false);
540 544 }
541 545 m_scrollButtonUp->setVisible(false);
542 546 m_scrollButtonDown->setVisible(false);
543 547
544 548 for (int i=0; i < m_markers.count(); i++) {
545 549 LegendMarker *m = m_markers.at(i);
546 550 if (i < mFirstMarker) {
547 551 // Markers before first are not visible.
548 552 m->setVisible(false);
549 553 } else {
550 554 if ((x + xStep + scrollButtonWidth + m_margin) > (m_pos.x() + m_maximumSize.width())) {
551 555 // This marker would go outside legend rect.
552 556 m->setVisible(false);
553 557 } else {
554 558 // This marker is ok
555 559 m->setVisible(true);
556 560 m->setPos(x, y);
557 561 x += xStep;
558 562 column++;
559 563 }
560 564 }
561 565 maxColumns = column;
562 566 }
563 567
564 568 m_scrollButtonLeft->setPos(m_pos.x() + m_margin, y);
565 569 m_scrollButtonRight->setPos(x + m_margin, y);
566 570
567 571 totalWidth += maxColumns * markerMaxSize.width() + m_margin * 2;
568 572 totalHeight = markerMaxSize.height() + m_margin * 2;
569 573
570 574 break;
571 575 }
572 576 // Both cases organize items vertically
573 577 case QLegend::AlignmentLeft:
574 578 case QLegend::AlignmentRight: {
575 579 qreal yStep = markerMaxSize.height();
576 580 qreal x = m_pos.x() + m_margin;
577 581 qreal y = m_pos.y() + m_margin;
578 582 int row = 1;
579 583 int maxRows = 1;
580 584 qreal scrollButtonHeight = 0;
581 585
582 586 // Set correct visibility for scroll scrollbuttons
583 587 if (scrollButtonsVisible()) {
584 588 m_scrollButtonUp->setVisible(true);
585 589 m_scrollButtonDown->setVisible(true);
586 590 totalHeight += (m_scrollButtonUp->boundingRect().height() + m_margin) * 2; // scrollbuttons visible, so add their height to total height
587 591 scrollButtonHeight = m_scrollButtonUp->boundingRect().height();
588 592 y += scrollButtonHeight + m_margin; // start position changes by scrollbutton height
589 593 } else {
590 594 m_scrollButtonUp->setVisible(false);
591 595 m_scrollButtonDown->setVisible(false);
592 596 }
593 597 m_scrollButtonLeft->setVisible(false);
594 598 m_scrollButtonRight->setVisible(false);
595 599
596 600 for (int i=0; i < m_markers.count(); i++) {
597 601 LegendMarker* m = m_markers.at(i);
598 602 if (i < mFirstMarker) {
599 603 // Markers before first are not visible.
600 604 m->setVisible(false);
601 605 } else {
602 606 if ((y + yStep + scrollButtonHeight) > (m_pos.y() + m_maximumSize.height())) {
603 607 // This marker would go outside legend rect.
604 608 m->setVisible(false);
605 609 } else {
606 610 // This marker is ok
607 611 m->setVisible(true);
608 612 m->setPos(x, y);
609 613 y += yStep;
610 614 row++;
611 615 }
612 616 }
613 617 maxRows = row;
614 618 }
615 619
616 620 m_scrollButtonUp->setPos(m_pos.x() + m_margin, m_pos.y() + m_margin);
617 621 m_scrollButtonDown->setPos(m_pos.x() + m_margin, y + m_margin);
618 622
619 623 totalWidth += markerMaxSize.width() + m_margin * 2;
620 624 totalHeight = maxRows * markerMaxSize.height() + m_margin * 4 + scrollButtonHeight; // TODO: check this
621 625 break;
622 626 }
623 627 default: {
624 628 break;
625 629 }
626 630 }
627 631
628 632 m_size.setWidth(totalWidth);
629 633 m_size.setHeight(totalHeight);
630 634
631 635 update();
632 636 }
633 637
634 638 /*!
635 639 \internal Sets the size of scroll buttons to \a size
636 640 */
637 641 void QLegend::rescaleScrollButtons(const QSize &size)
638 642 {
639 643 QPolygonF left;
640 644 left << QPointF(size.width(), 0) << QPointF(0, size.height() / 2) << QPointF(size.width(), size.height());
641 645 QPolygonF right;
642 646 right << QPointF(0, 0) << QPointF(size.width(), size.height() / 2) << QPointF(0, size.height());
643 647 QPolygonF up;
644 648 up << QPointF(0, size.height()) << QPointF(size.width() / 2,0) << QPointF(size.width(), size.height());
645 649 QPolygonF down;
646 650 down << QPointF(0, 0) << QPointF(size.width() / 2, size.height()) << QPointF(size.width(), 0);
647 651
648 652 m_scrollButtonLeft->setPolygon(left);
649 653 m_scrollButtonRight->setPolygon(right);
650 654 m_scrollButtonUp->setPolygon(up);
651 655 m_scrollButtonDown->setPolygon(down);
652 656 }
653 657
654 658 /*!
655 659 \internal Finds out maximum size of single marker. Marker sizes depend on series names.
656 660 */
657 661 QSizeF QLegend::maximumMarkerSize()
658 662 {
659 663 QSizeF max(0,0);
660 664 foreach (LegendMarker* m, m_markers) {
661 665 if (m->boundingRect().width() > max.width())
662 666 max.setWidth(m->boundingRect().width());
663 667 if (m->boundingRect().height() > max.height())
664 668 max.setHeight(m->boundingRect().height());
665 669 }
666 670 return max;
667 671 }
668 672
669 673 /*!
670 674 \internal Checks that first marker is in acceptable bounds. Bounds range from 0 to (maximum number of markers - visible markers)
671 675 If scrollbuttons are visible, they affect the number of visible markers.
672 676 */
673 677 void QLegend::checkFirstMarkerBounds()
674 678 {
675 679 if ((m_alignment == QLegend::AlignmentLeft) || (m_alignment == QLegend::AlignmentRight)) {
676 680 // Bounds limited by height.
677 681 int max;
678 682 if (scrollButtonsVisible()) {
679 683 max = (m_maximumSize.height() - m_scrollButtonLeft->boundingRect().height() * 2 - m_margin * 4) / maximumMarkerSize().height();
680 684 } else {
681 685 max = m_maximumSize.height() / maximumMarkerSize().height();
682 686 }
683 687
684 688 if (mFirstMarker > m_markers.count() - max)
685 689 mFirstMarker = m_markers.count() - max;
686 690 } else {
687 691 // Bounds limited by width
688 692 int max;
689 693 if (scrollButtonsVisible()) {
690 694 max = (m_maximumSize.width() - m_scrollButtonLeft->boundingRect().width() * 2 - m_margin*4) / maximumMarkerSize().width();
691 695 } else {
692 696 max = m_maximumSize.width() / maximumMarkerSize().width();
693 697 }
694 698
695 699 if (mFirstMarker > m_markers.count() - max)
696 700 mFirstMarker = m_markers.count() - max;
697 701 }
698 702
699 703 if (mFirstMarker < 0)
700 704 mFirstMarker = 0;
701 705 }
702 706
703 707 /*!
704 708 \internal Helper function. Visibility of scroll buttons isn't quite obvious, so helper function clarifies the logic.
705 709 */
706 710 bool QLegend::scrollButtonsVisible()
707 711 {
708 712 // Just a helper to clarify, what the magic below means :)
709 713 if ((m_alignment == QLegend::AlignmentTop) || (m_alignment == QLegend::AlignmentBottom)) {
710 714 return (maximumMarkerSize().width() * m_markers.count() + m_margin * 2 > m_maximumSize.width());
711 715 } else if ((m_alignment == QLegend::AlignmentLeft) || (m_alignment == QLegend::AlignmentRight)) {
712 716 return (maximumMarkerSize().height() * m_markers.count() + m_margin * 2 > m_maximumSize.height());
713 717 }
714 718
715 719 return (maximumMarkerSize().height() * m_markers.count() + m_margin * 2 > m_maximumSize.height());
716 720 }
717 721
718 722 #include "moc_qlegend.cpp"
719 723
720 724 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,140 +1,145
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #ifndef QLEGEND_H
22 22 #define QLEGEND_H
23 23
24 24 #include <QChartGlobal>
25 25 #include <QGraphicsWidget>
26 26 #include <QPen>
27 27 #include <QBrush>
28 28
29 29 QTCOMMERCIALCHART_BEGIN_NAMESPACE
30 30
31 31 class Domain;
32 32 class LegendMarker;
33 33 class QPieSlice;
34 34 class QXYSeries;
35 35 class QBarSet;
36 36 class QBarSeries;
37 37 class QPieSeries;
38 38 class QAreaSeries;
39 39 class LegendScrollButton;
40 40 class QSeries;
41 41 class QChart;
42 42
43 43 class QTCOMMERCIALCHART_EXPORT QLegend : public QGraphicsWidget
44 44 {
45 45 Q_OBJECT
46 46 public:
47 47
48 48 // We only support these alignments (for now)
49 49 enum Alignment {
50 50 AlignmentTop = Qt::AlignTop,
51 51 AlignmentBottom = Qt::AlignBottom,
52 52 AlignmentLeft = Qt::AlignLeft,
53 53 AlignmentRight = Qt::AlignRight
54 54 };
55
56 Q_DECLARE_FLAGS(Alignments, Alignment)
57
55 58 private:
56 59 explicit QLegend(QChart *chart);
57 60
58 61 public:
59 62 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
60 63 QRectF boundingRect() const;
61 64
62 65 void setBrush(const QBrush &brush);
63 66 QBrush brush() const;
64 67
65 68 void setPen(const QPen &pen);
66 69 QPen pen() const;
67 70
68 void setAlignmnent(QLegend::Alignment alignment);
69 QLegend::Alignment alignment() const;
71 void setAlignmnent(QLegend::Alignments alignment);
72 QLegend::Alignments alignment() const;
70 73
71 74 QSizeF maximumSize() const;
72 75 void setMaximumSize(const QSizeF size);
73 76
74 77 QSizeF size() const;
75 78 void setSize(const QSizeF size);
76 79 void setPos(const QPointF &pos);
77 80
78 81 void scrollButtonClicked(LegendScrollButton *scrollButton);
79 82
80 83 void detachFromChart();
81 84 void attachToChart();
82 85 bool attachedToChart();
83 86
84 87 Q_SIGNALS:
85 88 // for interactions.
86 89 void clicked(QSeries *series, Qt::MouseButton button);
87 90 void clicked(QBarSet *barset, Qt::MouseButton button);
88 91 void clicked(QPieSlice *slice, Qt::MouseButton button);
92 void legendGeometryChanged();
89 93
90 94 public Q_SLOTS:
91 95 // PIMPL --->
92 96 void handleSeriesAdded(QSeries *series, Domain *domain);
93 97 void handleSeriesRemoved(QSeries *series);
94 98 void handleAdded(QList<QPieSlice *> slices);
95 99 void handleRemoved(QList<QPieSlice *> slices);
96 100 void handleMarkerDestroyed();
97 101
98 102 // PIMPL <---
99 103
100 104 private:
101 105 // PIMPL --->
102 106 void appendMarkers(QAreaSeries *series);
103 107 void appendMarkers(QXYSeries *series);
104 108 void appendMarkers(QBarSeries *series);
105 109 void appendMarkers(QPieSeries *series);
106 110 void deleteMarkers(QSeries *series);
107 111 void updateLayout();
108 112 void rescaleScrollButtons(const QSize &size);
109 113 QSizeF maximumMarkerSize();
110 114 void checkFirstMarkerBounds();
111 115 bool scrollButtonsVisible();
112 116
113 117 qreal m_margin;
114 118 QPointF m_pos;
115 119 QSizeF m_minimumSize;
116 120 QSizeF m_maximumSize;
117 121 QSizeF m_size;
118 122
119 123 QList<LegendMarker *> m_markers;
120 124
121 125 QBrush m_brush;
122 126 QPen m_pen;
123 QLegend::Alignment m_alignment;
127 QLegend::Alignments m_alignment;
124 128
125 129 int mFirstMarker;
126 130
127 131 LegendScrollButton *m_scrollButtonLeft;
128 132 LegendScrollButton *m_scrollButtonRight;
129 133 LegendScrollButton *m_scrollButtonUp;
130 134 LegendScrollButton *m_scrollButtonDown;
131 135
132 136 bool m_attachedToChart;
133 137
138 QChart *m_chart;
134 139 friend class QChart;
135 140 // <--- PIMPL
136 141 };
137 142
138 143 QTCOMMERCIALCHART_END_NAMESPACE
139 144
140 145 #endif // QLEGEND_H
General Comments 0
You need to be logged in to leave comments. Login now