@@ -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 |
|
|
|
418 |
|
|
|
368 | rect.translate(-m_chart->padding().topLeft()); | |
|
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 |
|
|
|
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_p |
|
|
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_ |
|
|
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_ |
|
|
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 | { |
|
174 | m_alignment = alignment; | |
|
175 | updateLayout(); | |
|
175 | // if (!m_attachedToChart) { | |
|
176 | m_alignment = alignment; | |
|
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