##// END OF EJS Templates
legend refactoring.
sauimone -
r792:f33d64d30a1c
parent child
Show More
@@ -1,349 +1,348
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 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
39 39 **
40 40 ****************************************************************************/
41 41
42 42 #include "themewidget.h"
43 43
44 44 #include <QChartView>
45 45 #include <QPieSeries>
46 46 #include <QPieSlice>
47 47 #include <QBarSeries>
48 48 #include <QPercentBarSeries>
49 49 #include <QStackedBarSeries>
50 50 #include <QBarSet>
51 51 #include <QLineSeries>
52 52 #include <QSplineSeries>
53 53 #include <QScatterSeries>
54 54 #include <QAreaSeries>
55 55 #include <QGridLayout>
56 56 #include <QFormLayout>
57 57 #include <QComboBox>
58 58 #include <QSpinBox>
59 59 #include <QCheckBox>
60 60 #include <QGroupBox>
61 61 #include <QLabel>
62 62 #include <QTime>
63 63
64 64 ThemeWidget::ThemeWidget(QWidget* parent) :
65 65 QWidget(parent),
66 66 m_listCount(3),
67 67 m_valueMax(100),
68 68 m_valueCount(11),
69 69 m_dataTable(generateRandomData(m_listCount,m_valueMax,m_valueCount)),
70 70 m_themeComboBox(createThemeBox()),
71 71 m_antialiasCheckBox(new QCheckBox("Anti aliasing")),
72 72 m_animatedComboBox(createAnimationBox())
73 73 {
74 74
75 75 connectSignals();
76 76 // create layout
77 77 QGridLayout* baseLayout = new QGridLayout();
78 78 QHBoxLayout *settingsLayout = new QHBoxLayout();
79 79 settingsLayout->addWidget(new QLabel("Theme:"));
80 80 settingsLayout->addWidget(m_themeComboBox);
81 81 settingsLayout->addWidget(new QLabel("Animation:"));
82 82 settingsLayout->addWidget(m_animatedComboBox);
83 83 settingsLayout->addWidget(m_antialiasCheckBox);
84 84 settingsLayout->addStretch();
85 85 baseLayout->addLayout(settingsLayout, 0, 0, 1, 3);
86 86
87 87 //create charts
88 88
89 89 QChartView *chartView;
90 90
91 91 chartView = new QChartView(createAreaChart());
92 92 baseLayout->addWidget(chartView, 1, 0);
93 93 m_charts << chartView;
94 94
95 95 chartView = new QChartView(createBarChart(m_valueCount));
96 96 baseLayout->addWidget(chartView, 1, 1);
97 97 m_charts << chartView;
98 98
99 99 chartView = new QChartView(createLineChart());
100 100 baseLayout->addWidget(chartView, 1, 2);
101 101 m_charts << chartView;
102 102
103 103 chartView = new QChartView(createPieChart());
104 104 chartView->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored); // funny things happen if the pie slice labels no not fit the screen...
105 105 baseLayout->addWidget(chartView, 2, 0);
106 106 m_charts << chartView;
107 107
108 108 chartView = new QChartView(createSplineChart());
109 109 baseLayout->addWidget(chartView, 2, 1);
110 110 m_charts << chartView;
111 111
112 112 chartView = new QChartView(createScatterChart());
113 113 baseLayout->addWidget(chartView, 2, 2);
114 114 m_charts << chartView;
115 115
116 116 setLayout(baseLayout);
117 117 }
118 118
119 119 ThemeWidget::~ThemeWidget()
120 120 {
121 121 }
122 122
123 123 void ThemeWidget::connectSignals()
124 124 {
125 125 connect(m_themeComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(updateUI()));
126 126 connect(m_antialiasCheckBox, SIGNAL(toggled(bool)), this, SLOT(updateUI()));
127 127 connect(m_animatedComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(updateUI()));
128 128 }
129 129
130 130 DataTable ThemeWidget::generateRandomData(int listCount,int valueMax,int valueCount) const
131 131 {
132 132 DataTable dataTable;
133 133
134 134 // set seed for random stuff
135 135 qsrand(QTime(0, 0, 0).secsTo(QTime::currentTime()));
136 136
137 137 // generate random data
138 138 for (int i(0); i < listCount; i++) {
139 139 DataList dataList;
140 140 for (int j(0); j < valueCount; j++) {
141 141 QPointF value(j + (qreal) rand() / (qreal) RAND_MAX, qrand() % valueMax);
142 142 QString label = "Item " + QString::number(i) + ":" + QString::number(j);
143 143 dataList << Data(value, label);
144 144 }
145 145 dataTable << dataList;
146 146 }
147 147
148 148 return dataTable;
149 149 }
150 150
151 151 QComboBox* ThemeWidget::createThemeBox() const
152 152 {
153 153 // settings layout
154 154 QComboBox* themeComboBox = new QComboBox();
155 155 themeComboBox->addItem("Default", QChart::ChartThemeDefault);
156 156 themeComboBox->addItem("Light", QChart::ChartThemeLight);
157 157 themeComboBox->addItem("Blue Cerulean", QChart::ChartThemeBlueCerulean);
158 158 themeComboBox->addItem("Dark", QChart::ChartThemeDark);
159 159 themeComboBox->addItem("Brown Sand", QChart::ChartThemeBrownSand);
160 160 themeComboBox->addItem("Blue NCS", QChart::ChartThemeBlueNcs);
161 161 themeComboBox->addItem("High Contrast", QChart::ChartThemeHighContrast);
162 162 themeComboBox->addItem("Blue Icy", QChart::ChartThemeBlueIcy);
163 163 return themeComboBox;
164 164 }
165 165
166 166 QComboBox* ThemeWidget::createAnimationBox() const
167 167 {
168 168 // settings layout
169 169 QComboBox* animationComboBox = new QComboBox();
170 170 animationComboBox->addItem("No Animations", QChart::NoAnimation);
171 171 animationComboBox->addItem("GridAxis Animations", QChart::GridAxisAnimations);
172 172 animationComboBox->addItem("Series Animations", QChart::SeriesAnimations);
173 173 animationComboBox->addItem("All Animations", QChart::AllAnimations);
174 174 return animationComboBox;
175 175 }
176 176
177 177 QChart* ThemeWidget::createAreaChart() const
178 178 {
179 179 // area chart
180 180 QChart *chart = new QChart();
181 181 chart->setTitle("Area chart");
182 182 {
183 183 QString name("Series ");
184 184 int nameIndex = 0;
185 185 for (int i(0); i < m_dataTable.count(); i++) {
186 186 QLineSeries *series1 = new QLineSeries(chart);
187 187 QLineSeries *series2 = new QLineSeries(chart);
188 series1->setName(name + QString::number(nameIndex) + QString(" lo"));
189 series2->setName(name + QString::number(nameIndex) + QString(" hi"));
190 nameIndex++;
191 188 foreach (Data data, m_dataTable[i]) {
192 189 series1->add(data.first);
193 190 series2->add(QPointF(data.first.x(), 0.0));
194 191 }
195 192 QAreaSeries *area = new QAreaSeries(series1, series2);
193 area->setName(name + QString::number(nameIndex));
194 nameIndex++;
196 195 chart->addSeries(area);
197 196 }
198 197 }
199 198 return chart;
200 199 }
201 200
202 201 QChart* ThemeWidget::createBarChart(int valueCount) const
203 202 {
204 203 // bar chart
205 204 QChart* chart = new QChart();
206 205 chart->setTitle("Bar chart");
207 206 {
208 207 QBarCategories categories;
209 208 // TODO: categories
210 209 for (int i(0); i < valueCount; i++)
211 210 categories << QString::number(i);
212 211 // QBarSeries* series = new QBarSeries(categories, chart);
213 212 // QPercentBarSeries* series = new QPercentBarSeries(categories, chart);
214 213 QStackedBarSeries* series = new QStackedBarSeries(categories, chart);
215 214 for (int i(0); i < m_dataTable.count(); i++) {
216 215 QBarSet *set = new QBarSet("Set" + QString::number(i));
217 216 foreach (Data data, m_dataTable[i])
218 217 *set << data.first.y();
219 218 series->appendBarSet(set);
220 219 }
221 220 chart->addSeries(series);
222 221 }
223 222 return chart;
224 223 }
225 224
226 225 QChart* ThemeWidget::createLineChart() const
227 226 {
228 227 // line chart
229 228 QChart* chart = new QChart();
230 229 chart->setTitle("Line chart");
231 230 QString name("Series ");
232 231 int nameIndex = 0;
233 232 foreach (DataList list, m_dataTable) {
234 233 QLineSeries *series = new QLineSeries(chart);
235 234 foreach (Data data, list)
236 235 series->add(data.first);
237 236 series->setName(name + QString::number(nameIndex));
238 237 nameIndex++;
239 238 chart->addSeries(series);
240 239 }
241 240 return chart;
242 241 }
243 242
244 243 QChart* ThemeWidget::createPieChart() const
245 244 {
246 245 // pie chart
247 246 QChart* chart = new QChart();
248 247 chart->setTitle("Pie chart");
249 248 qreal pieSize = 1.0 / m_dataTable.count();
250 249 for (int i = 0; i < m_dataTable.count(); i++) {
251 250 QPieSeries *series = new QPieSeries(chart);
252 251 foreach (Data data, m_dataTable[i]) {
253 252 QPieSlice *slice = series->add(data.first.y(), data.second);
254 253 if (data == m_dataTable[i].first()) {
255 254 slice->setLabelVisible();
256 255 slice->setExploded();
257 256 }
258 257 }
259 258 qreal hPos = (pieSize / 2) + (i / (qreal) m_dataTable.count());
260 259 series->setPieSize(pieSize);
261 260 series->setPiePosition(hPos, 0.5);
262 261 chart->addSeries(series);
263 262 }
264 263
265 264 return chart;
266 265 }
267 266
268 267 QChart* ThemeWidget::createSplineChart() const
269 268 { // spine chart
270 269 QChart* chart = new QChart();
271 270 chart->setTitle("Spline chart");
272 271 QString name("Series ");
273 272 int nameIndex = 0;
274 273 foreach (DataList list, m_dataTable) {
275 274 QSplineSeries *series = new QSplineSeries(chart);
276 275 foreach (Data data, list)
277 276 series->add(data.first);
278 277 series->setName(name + QString::number(nameIndex));
279 278 nameIndex++;
280 279 chart->addSeries(series);
281 280 }
282 281 return chart;
283 282 }
284 283
285 284 QChart* ThemeWidget::createScatterChart() const
286 285 { // scatter chart
287 286 QChart* chart = new QChart();
288 287 chart->setTitle("Scatter chart");
289 288 QString name("Series ");
290 289 int nameIndex = 0;
291 290 foreach (DataList list, m_dataTable) {
292 291 QScatterSeries *series = new QScatterSeries(chart);
293 292 foreach (Data data, list)
294 293 series->add(data.first);
295 294 series->setName(name + QString::number(nameIndex));
296 295 nameIndex++;
297 296 chart->addSeries(series);
298 297 }
299 298 return chart;
300 299 }
301 300
302 301 void ThemeWidget::updateUI()
303 302 {
304 303 QChart::ChartTheme theme = (QChart::ChartTheme) m_themeComboBox->itemData(m_themeComboBox->currentIndex()).toInt();
305 304
306 305 if (m_charts.at(0)->chart()->theme() != theme) {
307 306 foreach (QChartView *chartView, m_charts)
308 307 chartView->chart()->setTheme(theme);
309 308
310 309 QPalette pal = window()->palette();
311 310 if (theme == QChart::ChartThemeLight) {
312 311 pal.setColor(QPalette::Window, QRgb(0xf0f0f0));
313 312 pal.setColor(QPalette::WindowText, QRgb(0x404044));
314 313 } else if (theme == QChart::ChartThemeDark) {
315 314 pal.setColor(QPalette::Window, QRgb(0x121218));
316 315 pal.setColor(QPalette::WindowText, QRgb(0xd6d6d6));
317 316 } else if (theme == QChart::ChartThemeBlueCerulean) {
318 317 pal.setColor(QPalette::Window, QRgb(0x40434a));
319 318 pal.setColor(QPalette::WindowText, QRgb(0xd6d6d6));
320 319 } else if (theme == QChart::ChartThemeBrownSand) {
321 320 pal.setColor(QPalette::Window, QRgb(0x9e8965));
322 321 pal.setColor(QPalette::WindowText, QRgb(0x404044));
323 322 } else if (theme == QChart::ChartThemeBlueNcs) {
324 323 pal.setColor(QPalette::Window, QRgb(0x018bba));
325 324 pal.setColor(QPalette::WindowText, QRgb(0x404044));
326 325 } else if (theme == QChart::ChartThemeHighContrast) {
327 326 pal.setColor(QPalette::Window, QRgb(0xffab03));
328 327 pal.setColor(QPalette::WindowText, QRgb(0x181818));
329 328 } else if (theme == QChart::ChartThemeBlueIcy) {
330 329 pal.setColor(QPalette::Window, QRgb(0xcee7f0));
331 330 pal.setColor(QPalette::WindowText, QRgb(0x404044));
332 331 } else {
333 332 pal.setColor(QPalette::Window, QRgb(0xf0f0f0));
334 333 pal.setColor(QPalette::WindowText, QRgb(0x404044));
335 334 }
336 335 window()->setPalette(pal);
337 336 }
338 337
339 338 bool checked = m_antialiasCheckBox->isChecked();
340 339 foreach (QChartView *chart, m_charts)
341 340 chart->setRenderHint(QPainter::Antialiasing, checked);
342 341
343 342 QChart::AnimationOptions options(m_animatedComboBox->itemData(m_animatedComboBox->currentIndex()).toInt());
344 343 if (m_charts.at(0)->chart()->animationOptions() != options) {
345 344 foreach (QChartView *chartView, m_charts)
346 345 chartView->chart()->setAnimationOptions(options);
347 346 }
348 347 }
349 348
@@ -1,386 +1,385
1 1 #include "qchart.h"
2 2 #include "qlegend.h"
3 3 #include "qchartaxis.h"
4 4 #include "chartpresenter_p.h"
5 5 #include "chartdataset_p.h"
6 6 #include "charttheme_p.h"
7 7 #include "chartanimator_p.h"
8 8 //series
9 9 #include "qbarseries.h"
10 10 #include "qstackedbarseries.h"
11 11 #include "qpercentbarseries.h"
12 12 #include "qlineseries.h"
13 13 #include "qareaseries.h"
14 14 #include "qpieseries.h"
15 15 #include "qscatterseries.h"
16 16 #include "qsplineseries.h"
17 17 //items
18 18 #include "axisitem_p.h"
19 19 #include "areachartitem_p.h"
20 20 #include "barchartitem_p.h"
21 21 #include "stackedbarchartitem_p.h"
22 22 #include "percentbarchartitem_p.h"
23 23 #include "linechartitem_p.h"
24 24 #include "piechartitem_p.h"
25 25 #include "scatterchartitem_p.h"
26 26 #include "splinechartitem_p.h"
27 27
28 28 QTCOMMERCIALCHART_BEGIN_NAMESPACE
29 29
30 30 ChartPresenter::ChartPresenter(QChart* chart,ChartDataSet* dataset):QObject(chart),
31 31 m_chart(chart),
32 32 m_animator(0),
33 33 m_dataset(dataset),
34 34 m_chartTheme(0),
35 35 m_rect(QRectF(QPoint(0,0),m_chart->size())),
36 36 m_options(QChart::NoAnimation),
37 37 m_themeForce(false),
38 38 m_padding(50),
39 39 m_backgroundPadding(10)
40 40 {
41 41 createConnections();
42 42 setTheme(QChart::ChartThemeDefault,false);
43 43 }
44 44
45 45 ChartPresenter::~ChartPresenter()
46 46 {
47 47 delete m_chartTheme;
48 48 }
49 49
50 50 void ChartPresenter::createConnections()
51 51 {
52 52 QObject::connect(m_chart,SIGNAL(geometryChanged()),this,SLOT(handleGeometryChanged()));
53 53 QObject::connect(m_dataset,SIGNAL(seriesAdded(QSeries*,Domain*)),this,SLOT(handleSeriesAdded(QSeries*,Domain*)));
54 54 QObject::connect(m_dataset,SIGNAL(seriesRemoved(QSeries*)),this,SLOT(handleSeriesRemoved(QSeries*)));
55 55 QObject::connect(m_dataset,SIGNAL(axisAdded(QChartAxis*,Domain*)),this,SLOT(handleAxisAdded(QChartAxis*,Domain*)));
56 56 QObject::connect(m_dataset,SIGNAL(axisRemoved(QChartAxis*)),this,SLOT(handleAxisRemoved(QChartAxis*)));
57 57 }
58 58
59 59 void ChartPresenter::handleGeometryChanged()
60 60 {
61 qDebug() << "legend h:" << m_chart->legend()->size().height();
62 61 QRectF rect(QPoint(0,0),m_chart->size());
63 62 rect.adjust(m_padding,
64 63 m_padding + m_chart->legend()->size().height(),
65 64 -m_padding,
66 65 -m_padding);
67 66
68 67 //rewrite zoom stack
69 68 /*
70 69 for(int i=0;i<m_zoomStack.count();i++){
71 70 QRectF r = m_zoomStack[i];
72 71 qreal w = rect.width()/m_rect.width();
73 72 qreal h = rect.height()/m_rect.height();
74 73 QPointF tl = r.topLeft();
75 74 tl.setX(tl.x()*w);
76 75 tl.setY(tl.y()*h);
77 76 QPointF br = r.bottomRight();
78 77 br.setX(br.x()*w);
79 78 br.setY(br.y()*h);
80 79 r.setTopLeft(tl);
81 80 r.setBottomRight(br);
82 81 m_zoomStack[i]=r;
83 82 }
84 83 */
85 84 m_rect = rect;
86 85 Q_ASSERT(m_rect.isValid());
87 86 emit geometryChanged(m_rect);
88 87 }
89 88
90 89 void ChartPresenter::handleAxisAdded(QChartAxis* axis,Domain* domain)
91 90 {
92 91 Axis* item = new Axis(axis,this,axis==m_dataset->axisX()?Axis::X_AXIS : Axis::Y_AXIS);
93 92
94 93 if(m_options.testFlag(QChart::GridAxisAnimations)){
95 94 m_animator->addAnimation(item);
96 95 }
97 96
98 97 if(axis==m_dataset->axisX()){
99 98 m_chartTheme->decorate(axis,true,m_themeForce);
100 99 QObject::connect(domain,SIGNAL(rangeXChanged(qreal,qreal,int)),item,SLOT(handleRangeChanged(qreal,qreal,int)));
101 100 //initialize
102 101 item->handleRangeChanged(domain->minX(),domain->maxX(),domain->tickXCount());
103 102
104 103 }
105 104 else{
106 105 m_chartTheme->decorate(axis,false,m_themeForce);
107 106 QObject::connect(domain,SIGNAL(rangeYChanged(qreal,qreal,int)),item,SLOT(handleRangeChanged(qreal,qreal,int)));
108 107 //initialize
109 108 item->handleRangeChanged(domain->minY(),domain->maxY(),domain->tickYCount());
110 109 }
111 110
112 111 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),item,SLOT(handleGeometryChanged(const QRectF&)));
113 112 //initialize
114 113 item->handleGeometryChanged(m_rect);
115 114 m_axisItems.insert(axis, item);
116 115 }
117 116
118 117 void ChartPresenter::handleAxisRemoved(QChartAxis* axis)
119 118 {
120 119 Axis* item = m_axisItems.take(axis);
121 120 Q_ASSERT(item);
122 121 if(m_animator) m_animator->removeAnimation(item);
123 122 delete item;
124 123 }
125 124
126 125
127 126 void ChartPresenter::handleSeriesAdded(QSeries* series,Domain* domain)
128 127 {
129 128 Chart *item = 0 ;
130 129
131 130 switch(series->type())
132 131 {
133 132 case QSeries::SeriesTypeLine: {
134 133
135 134 QLineSeries* lineSeries = static_cast<QLineSeries*>(series);
136 135 LineChartItem* line = new LineChartItem(lineSeries,this);
137 136 if(m_options.testFlag(QChart::SeriesAnimations)) {
138 137 m_animator->addAnimation(line);
139 138 }
140 139 m_chartTheme->decorate(lineSeries, m_dataset->seriesIndex(series),m_themeForce);
141 140 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),line,SLOT(handleGeometryChanged(const QRectF&)));
142 141 QObject::connect(domain,SIGNAL(domainChanged(qreal,qreal,qreal,qreal)),line,SLOT(handleDomainChanged(qreal,qreal,qreal,qreal)));
143 142 item = line;
144 143 break;
145 144 }
146 145
147 146 case QSeries::SeriesTypeArea: {
148 147
149 148 QAreaSeries* areaSeries = static_cast<QAreaSeries*>(series);
150 149 AreaChartItem* area = new AreaChartItem(areaSeries,this);
151 150 if(m_options.testFlag(QChart::SeriesAnimations)) {
152 151 m_animator->addAnimation(area->upperLineItem());
153 152 if(areaSeries->lowerSeries()) m_animator->addAnimation(area->lowerLineItem());
154 153 }
155 154 m_chartTheme->decorate(areaSeries, m_dataset->seriesIndex(series),m_themeForce);
156 155 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),area,SLOT(handleGeometryChanged(const QRectF&)));
157 156 QObject::connect(domain,SIGNAL(domainChanged(qreal,qreal,qreal,qreal)),area,SLOT(handleDomainChanged(qreal,qreal,qreal,qreal)));
158 157 item=area;
159 158 break;
160 159 }
161 160
162 161 case QSeries::SeriesTypeBar: {
163 162 QBarSeries* barSeries = static_cast<QBarSeries*>(series);
164 163 BarChartItem* bar = new BarChartItem(barSeries,this);
165 164 if(m_options.testFlag(QChart::SeriesAnimations)) {
166 165 m_animator->addAnimation(bar);
167 166 }
168 167 m_chartTheme->decorate(barSeries, m_dataset->seriesIndex(barSeries),m_themeForce);
169 168 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),bar,SLOT(handleGeometryChanged(const QRectF&)));
170 169 QObject::connect(domain,SIGNAL(domainChanged(qreal,qreal,qreal,qreal)),bar,SLOT(handleDomainChanged(qreal,qreal,qreal,qreal)));
171 170 item=bar;
172 171 break;
173 172 }
174 173
175 174 case QSeries::SeriesTypeStackedBar: {
176 175 QStackedBarSeries* stackedBarSeries = static_cast<QStackedBarSeries*>(series);
177 176 StackedBarChartItem* bar = new StackedBarChartItem(stackedBarSeries,this);
178 177 if(m_options.testFlag(QChart::SeriesAnimations)) {
179 178 m_animator->addAnimation(bar);
180 179 }
181 180 m_chartTheme->decorate(stackedBarSeries, m_dataset->seriesIndex(stackedBarSeries),m_themeForce);
182 181 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),bar,SLOT(handleGeometryChanged(const QRectF&)));
183 182 QObject::connect(domain,SIGNAL(domainChanged(qreal,qreal,qreal,qreal)),bar,SLOT(handleDomainChanged(qreal,qreal,qreal,qreal)));
184 183 item=bar;
185 184 break;
186 185 }
187 186
188 187 case QSeries::SeriesTypePercentBar: {
189 188 QPercentBarSeries* percentBarSeries = static_cast<QPercentBarSeries*>(series);
190 189 PercentBarChartItem* bar = new PercentBarChartItem(percentBarSeries,this);
191 190 if(m_options.testFlag(QChart::SeriesAnimations)) {
192 191 m_animator->addAnimation(bar);
193 192 }
194 193 m_chartTheme->decorate(percentBarSeries, m_dataset->seriesIndex(percentBarSeries),m_themeForce);
195 194 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),bar,SLOT(handleGeometryChanged(const QRectF&)));
196 195 QObject::connect(domain,SIGNAL(domainChanged(qreal,qreal,qreal,qreal)),bar,SLOT(handleDomainChanged(qreal,qreal,qreal,qreal)));
197 196 item=bar;
198 197 break;
199 198 }
200 199
201 200 case QSeries::SeriesTypeScatter: {
202 201 QScatterSeries *scatterSeries = static_cast<QScatterSeries *>(series);
203 202 ScatterChartItem *scatter = new ScatterChartItem(scatterSeries,this);
204 203 if(m_options.testFlag(QChart::SeriesAnimations)) {
205 204 m_animator->addAnimation(scatter);
206 205 }
207 206 m_chartTheme->decorate(scatterSeries, m_dataset->seriesIndex(series),m_themeForce);
208 207 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),scatter,SLOT(handleGeometryChanged(const QRectF&)));
209 208 QObject::connect(domain,SIGNAL(domainChanged(qreal,qreal,qreal,qreal)),scatter,SLOT(handleDomainChanged(qreal,qreal,qreal,qreal)));
210 209 item = scatter;
211 210 break;
212 211 }
213 212
214 213 case QSeries::SeriesTypePie: {
215 214 QPieSeries *pieSeries = static_cast<QPieSeries *>(series);
216 215 PieChartItem* pie = new PieChartItem(pieSeries, this);
217 216 if(m_options.testFlag(QChart::SeriesAnimations)) {
218 217 m_animator->addAnimation(pie);
219 218 }
220 219 m_chartTheme->decorate(pieSeries, m_dataset->seriesIndex(series),m_themeForce);
221 220 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),pie,SLOT(handleGeometryChanged(const QRectF&)));
222 221 QObject::connect(domain,SIGNAL(domainChanged(qreal,qreal,qreal,qreal)),pie,SLOT(handleDomainChanged(qreal,qreal,qreal,qreal)));
223 222 // Hide all from background when there is only piechart
224 223 // TODO: refactor this ugly code... should be one setting for this
225 224 if (m_chartItems.count() == 0) {
226 225 m_chart->axisX()->hide();
227 226 m_chart->axisY()->hide();
228 227 }
229 228 item=pie;
230 229 break;
231 230 }
232 231
233 232 case QSeries::SeriesTypeSpline: {
234 233 QSplineSeries* splineSeries = static_cast<QSplineSeries*>(series);
235 234 SplineChartItem* spline = new SplineChartItem(splineSeries, this);
236 235 if(m_options.testFlag(QChart::SeriesAnimations)) {
237 236 m_animator->addAnimation(spline);
238 237 }
239 238 m_chartTheme->decorate(splineSeries, m_dataset->seriesIndex(series),m_themeForce);
240 239 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),spline,SLOT(handleGeometryChanged(const QRectF&)));
241 240 QObject::connect(domain,SIGNAL(domainChanged(qreal,qreal,qreal,qreal)),spline,SLOT(handleDomainChanged(qreal,qreal,qreal,qreal)));
242 241 item=spline;
243 242 break;
244 243 }
245 244 default: {
246 245 qDebug()<< "Series type" << series->type() << "not implemented.";
247 246 break;
248 247 }
249 248 }
250 249
251 250 //initialize
252 251 item->handleDomainChanged(domain->minX(),domain->maxX(),domain->minY(),domain->maxY());
253 252 if(m_rect.isValid()) item->handleGeometryChanged(m_rect);
254 253 m_chartItems.insert(series,item);
255 254 }
256 255
257 256 void ChartPresenter::handleSeriesRemoved(QSeries* series)
258 257 {
259 258 Chart* item = m_chartItems.take(series);
260 259 Q_ASSERT(item);
261 260 if(m_animator) {
262 261 //small hack to handle area animations
263 262 if(series->type()==QSeries::SeriesTypeArea){
264 263 QAreaSeries* areaSeries = static_cast<QAreaSeries*>(series);
265 264 AreaChartItem* area = static_cast<AreaChartItem*>(item);
266 265 m_animator->removeAnimation(area->upperLineItem());
267 266 if(areaSeries->lowerSeries()) m_animator->removeAnimation(area->lowerLineItem());
268 267 }else
269 268 m_animator->removeAnimation(item);
270 269 }
271 270 delete item;
272 271 }
273 272
274 273 void ChartPresenter::setTheme(QChart::ChartTheme theme,bool force)
275 274 {
276 275 if(m_chartTheme && m_chartTheme->id() == theme) return;
277 276 delete m_chartTheme;
278 277 m_themeForce = force;
279 278 m_chartTheme = ChartTheme::createTheme(theme);
280 279 m_chartTheme->decorate(m_chart,m_themeForce);
281 280 m_chartTheme->decorate(m_chart->legend(),m_themeForce);
282 281 resetAllElements();
283 282 }
284 283
285 284 QChart::ChartTheme ChartPresenter::theme()
286 285 {
287 286 return m_chartTheme->id();
288 287 }
289 288
290 289 void ChartPresenter::setAnimationOptions(QChart::AnimationOptions options)
291 290 {
292 291 if(m_options!=options) {
293 292
294 293 m_options=options;
295 294
296 295 if(m_options!=QChart::NoAnimation && !m_animator) {
297 296 m_animator= new ChartAnimator(this);
298 297
299 298 }
300 299 resetAllElements();
301 300 }
302 301
303 302 }
304 303
305 304 void ChartPresenter::resetAllElements()
306 305 {
307 306 QList<QChartAxis*> axisList = m_axisItems.uniqueKeys();
308 307 QList<QSeries*> seriesList = m_chartItems.uniqueKeys();
309 308
310 309 foreach(QChartAxis* axis, axisList) {
311 310 handleAxisRemoved(axis);
312 311 handleAxisAdded(axis,m_dataset->domain(axis));
313 312 }
314 313 foreach(QSeries* series, seriesList) {
315 314 handleSeriesRemoved(series);
316 315 handleSeriesAdded(series,m_dataset->domain(series));
317 316 }
318 317 }
319 318
320 319 void ChartPresenter::zoomIn()
321 320 {
322 321 QRectF rect = geometry();
323 322 rect.setWidth(rect.width()/2);
324 323 rect.setHeight(rect.height()/2);
325 324 rect.moveCenter(geometry().center());
326 325 zoomIn(rect);
327 326 }
328 327
329 328 void ChartPresenter::zoomIn(const QRectF& rect)
330 329 {
331 330 QRectF r = rect.normalized();
332 331 r.translate(-m_padding, -m_padding);
333 332 if(m_animator) {
334 333
335 334 QPointF point(r.center().x()/geometry().width(),r.center().y()/geometry().height());
336 335 m_animator->setState(ChartAnimator::ZoomInState,point);
337 336 }
338 337 m_dataset->zoomInDomain(r,geometry().size());
339 338 if(m_animator) {
340 339 m_animator->setState(ChartAnimator::ShowState);
341 340 }
342 341 }
343 342
344 343 void ChartPresenter::zoomOut()
345 344 {
346 345 if(m_animator)
347 346 {
348 347 m_animator->setState(ChartAnimator::ZoomOutState);
349 348 }
350 349
351 350 QSizeF size = geometry().size();
352 351 QRectF rect = geometry();
353 352 rect.translate(-m_padding, -m_padding);
354 353 m_dataset->zoomOutDomain(rect.adjusted(size.width()/4,size.height()/4,-size.width()/4,-size.height()/4),size);
355 354 //m_dataset->zoomOutDomain(m_zoomStack[m_zoomIndex-1],geometry().size());
356 355
357 356 if(m_animator){
358 357 m_animator->setState(ChartAnimator::ShowState);
359 358 }
360 359 }
361 360
362 361 void ChartPresenter::scroll(int dx,int dy)
363 362 {
364 363 if(m_animator){
365 364 if(dx<0) m_animator->setState(ChartAnimator::ScrollLeftState,QPointF());
366 365 if(dx>0) m_animator->setState(ChartAnimator::ScrollRightState,QPointF());
367 366 if(dy<0) m_animator->setState(ChartAnimator::ScrollUpState,QPointF());
368 367 if(dy>0) m_animator->setState(ChartAnimator::ScrollDownState,QPointF());
369 368 }
370 369
371 370 m_dataset->scrollDomain(dx,dy,geometry().size());
372 371
373 372 if(m_animator){
374 373 m_animator->setState(ChartAnimator::ShowState);
375 374 }
376 375 }
377 376
378 377 QChart::AnimationOptions ChartPresenter::animationOptions() const
379 378 {
380 379 return m_options;
381 380 }
382 381
383 382
384 383 #include "moc_chartpresenter_p.cpp"
385 384
386 385 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,175 +1,190
1 1 #include "qchartglobal.h"
2 2 #include "legendmarker_p.h"
3 3 #include <qpieslice.h>
4 4 #include <qbarset.h>
5 5 #include <qxyseries.h>
6 #include <qareaseries.h>
6 7 #include <QPainter>
7 8 #include <QGraphicsSceneEvent>
8 9 #include <QGraphicsSimpleTextItem>
9 10
10 11 QTCOMMERCIALCHART_BEGIN_NAMESPACE
11 12
12 13 LegendMarker::LegendMarker(QSeries *series, QGraphicsItem *parent) : QGraphicsObject(parent),
13 14 m_pos(0,0),
14 15 m_size(0,0),
15 16 m_boundingRect(0,0,0,0),
16 17 m_markerBoundingRect(0,0,0,0),
17 18 m_series(series),
18 19 m_barset(0),
19 20 m_pieslice(0),
20 m_type(LegendMarkerTypeSeries),
21 21 m_textItem(new QGraphicsSimpleTextItem(this))
22 22 {
23 23 setAcceptedMouseButtons(Qt::LeftButton|Qt::RightButton);
24 24 }
25 25
26 26 LegendMarker::LegendMarker(QSeries *series, QBarSet *barset, QGraphicsItem *parent) : QGraphicsObject(parent),
27 27 m_pos(0,0),
28 28 m_size(0,0),
29 29 m_boundingRect(0,0,0,0),
30 30 m_markerBoundingRect(0,0,0,0),
31 31 m_series(series),
32 32 m_barset(barset),
33 33 m_pieslice(0),
34 m_type(LegendMarkerTypeBarset),
35 34 m_textItem(new QGraphicsSimpleTextItem(this))
36 35 {
37 36 setAcceptedMouseButtons(Qt::LeftButton|Qt::RightButton);
38 37 }
39 38
40 39 LegendMarker::LegendMarker(QSeries *series, QPieSlice *pieslice, QGraphicsItem *parent) : QGraphicsObject(parent),
41 40 m_pos(0,0),
42 41 m_size(0,0),
43 42 m_boundingRect(0,0,0,0),
44 43 m_markerBoundingRect(0,0,0,0),
45 44 m_series(series),
46 45 m_barset(0),
47 46 m_pieslice(pieslice),
48 m_type(LegendMarkerTypePieslice),
49 47 m_textItem(new QGraphicsSimpleTextItem(this))
50 48 {
51 49 setAcceptedMouseButtons(Qt::LeftButton|Qt::RightButton);
52 50 }
53 51
54 52 void LegendMarker::setPos(qreal x, qreal y)
55 53 {
56 54 m_pos = QPointF(x,y);
57 55 layoutChanged();
58 56 }
59 57
60 58 void LegendMarker::setPen(const QPen &pen)
61 59 {
62 60 m_pen = pen;
63 61 }
64 62
65 63 QPen LegendMarker::pen() const
66 64 {
67 65 return m_pen;
68 66 }
69 67
70 68 void LegendMarker::setBrush(const QBrush &brush)
71 69 {
72 70 m_brush = brush;
73 71 }
74 72
75 73 QBrush LegendMarker::brush() const
76 74 {
77 75 return m_brush;
78 76 }
79 77
80 78 void LegendMarker::setName(const QString name)
81 79 {
82 80 m_textItem->setText(name);
83 81 layoutChanged();
84 82 }
85 83
86 84 QString LegendMarker::name() const
87 85 {
88 86 return m_textItem->text();
89 87 }
90 88
91 89 QSeries* LegendMarker::series() const
92 90 {
93 91 return m_series;
94 92 }
95 93
96 94 void LegendMarker::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
97 95 {
98 96 Q_UNUSED(option)
99 97 Q_UNUSED(widget)
100 98
101 99 painter->setPen(m_pen);
102 100 painter->setBrush(m_brush);
103 101 painter->drawRect(m_markerBoundingRect);
104 102 }
105 103
106 104 QRectF LegendMarker::boundingRect() const
107 105 {
108 106 return m_boundingRect;
109 107 }
110 108
111 109 void LegendMarker::layoutChanged()
112 110 {
113 111 QSizeF markerSize(10,10);
114 112 qreal margin = 2;
115 113
116 114 m_size.setHeight(markerSize.height() + 2 * margin);
117 115 m_size.setWidth(m_textItem->boundingRect().width() + markerSize.width() + 3 * margin);
118 116
119 117 m_boundingRect = QRectF(m_pos.x(),m_pos.y(),m_size.width(),m_size.height());
120 118
121 119 m_markerBoundingRect = QRectF(m_pos.x() + margin, m_pos.y() + margin, markerSize.width(),markerSize.height());
122 120
123 121 m_textItem->setPos(m_pos.x() + markerSize.width() + 2 * margin, m_pos.y() + margin);
124 122 }
125 123
126 124 void LegendMarker::mousePressEvent(QGraphicsSceneMouseEvent *event)
127 125 {
128 switch (m_type)
129 {
130 case LegendMarkerTypeSeries: {
126 switch (m_series->type()) {
127 case QSeries::SeriesTypeLine:
128 case QSeries::SeriesTypeArea:
129 case QSeries::SeriesTypeScatter:
130 case QSeries::SeriesTypeSpline: {
131 131 emit clicked(m_series,event->button());
132 132 break;
133 133 }
134 case LegendMarkerTypeBarset: {
134 case QSeries::SeriesTypeBar:
135 case QSeries::SeriesTypeStackedBar:
136 case QSeries::SeriesTypePercentBar: {
135 137 emit clicked(m_barset,event->button());
136 138 break;
137 139 }
138 case LegendMarkerTypePieslice: {
140 case QSeries::SeriesTypePie: {
139 141 emit clicked(m_pieslice,event->button());
140 142 break;
141 143 }
142 144 default: {
143 145 break;
144 146 }
145 147 }
146 148 }
147 149
148 150 void LegendMarker::changed()
149 151 {
150 switch (m_type)
151 {
152 case LegendMarkerTypeSeries: {
153 QXYSeries* s = static_cast<QXYSeries*> (m_series);
152 switch (m_series->type()) {
153 case QSeries::SeriesTypeArea: {
154 QAreaSeries* s = static_cast<QAreaSeries*> (m_series);
154 155 setPen(s->pen());
155 156 setBrush(s->brush());
156 157 setName(s->name());
157 158 break;
158 159 }
159 case LegendMarkerTypeBarset: {
160 case QSeries::SeriesTypeLine:
161 case QSeries::SeriesTypeScatter:
162 case QSeries::SeriesTypeSpline: {
163 QXYSeries* s = static_cast<QXYSeries*> (m_series);
164 setPen(s->pen());
165 setBrush(s->brush());
166 setName(s->name());
167 break;
168 }
169 case QSeries::SeriesTypeBar:
170 case QSeries::SeriesTypeStackedBar:
171 case QSeries::SeriesTypePercentBar: {
160 172 setPen(m_barset->pen());
161 173 setBrush(m_barset->brush());
162 174 setName(m_barset->name());
163 175 break;
164 }
165 case LegendMarkerTypePieslice: {
176 }
177 case QSeries::SeriesTypePie: {
166 178 setBrush(m_pieslice->brush());
167 179 setName(m_pieslice->label());
168 180 break;
169 }
181 }
182 default: {
183 break;
184 }
170 185 }
171 186 }
172 187
173 188 #include "moc_legendmarker_p.cpp"
174 189
175 190 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,81 +1,74
1 1 #ifndef LEGENDMARKER_P_H
2 2 #define LEGENDMARKER_P_H
3 3
4 4 #include "qchartglobal.h"
5 5 #include <QGraphicsObject>
6 6 #include <QBrush>
7 7 #include <QPen>
8 8 #include <QGraphicsSimpleTextItem>
9 9
10 10 QTCOMMERCIALCHART_BEGIN_NAMESPACE
11 11
12 12 class QSeries;
13 13 class QBarSet;
14 14 class QPieSlice;
15 15
16 16 // TODO: split this to 3 different markers for series, barset and pieslice. Current implementation is easier to misuse...
17 17 class LegendMarker : public QGraphicsObject
18 18 {
19 19 Q_OBJECT
20 20
21 enum LegendMarkerType {
22 LegendMarkerTypeSeries,
23 LegendMarkerTypeBarset,
24 LegendMarkerTypePieslice
25 };
26
27 21 public:
28 22 LegendMarker(QSeries *series, QGraphicsItem *parent = 0);
29 23 LegendMarker(QSeries *series, QBarSet *barset, QGraphicsItem *parent = 0);
30 24 LegendMarker(QSeries *series, QPieSlice *pieslice, QGraphicsItem *parent = 0);
31 25
32 26 void setPos(qreal x, qreal y);
33 27
34 28 void setPen(const QPen &pen);
35 29 QPen pen() const;
36 30
37 31 void setBrush(const QBrush &brush);
38 32 QBrush brush() const;
39 33
40 34 void setName(const QString name);
41 35 QString name() const;
42 36
43 37 QSeries* series() const;
44 38
45 39 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
46 40
47 41 QRectF boundingRect() const;
48 42
49 43 void layoutChanged();
50 44
51 45 public:
52 46 // From QGraphicsObject
53 47 void mousePressEvent(QGraphicsSceneMouseEvent *event);
54 48
55 49 Q_SIGNALS:
56 50 void clicked(QSeries *series, Qt::MouseButton button);
57 51 void clicked(QBarSet *barset, Qt::MouseButton button);
58 52 void clicked(QPieSlice *pieslice, Qt::MouseButton button);
59 53
60 54 public Q_SLOTS:
61 55 void changed();
62 56
63 57 private:
64 58 QPointF m_pos;
65 59 QSize m_size;
66 60 QRectF m_boundingRect;
67 61 QRectF m_markerBoundingRect;
68 62 QBrush m_brush;
69 63 QPen m_pen;
70 64
71 65 QSeries *m_series;
72 66 QBarSet *m_barset;
73 67 QPieSlice *m_pieslice;
74 68
75 LegendMarkerType m_type;
76 69 QGraphicsSimpleTextItem *m_textItem;
77 70
78 71 };
79 72
80 73 QTCOMMERCIALCHART_END_NAMESPACE
81 74 #endif // LEGENDMARKER_P_H
@@ -1,693 +1,683
1 1 #include "qlegend.h"
2 2 #include "qchart_p.h"
3 3 #include "qseries.h"
4 4 #include "legendmarker_p.h"
5 5 #include "legendscrollbutton_p.h"
6 6 #include "qxyseries.h"
7 7 #include "qlineseries.h"
8 8 #include "qareaseries.h"
9 9 #include "qscatterseries.h"
10 10 #include "qsplineseries.h"
11 11 #include "qbarseries.h"
12 12 #include "qstackedbarseries.h"
13 13 #include "qpercentbarseries.h"
14 14 #include "qbarset.h"
15 15 #include "qpieseries.h"
16 16 #include "qpieslice.h"
17 17 #include "chartpresenter_p.h"
18 18 #include <QPainter>
19 19 #include <QPen>
20 20
21 21 #include <QGraphicsSceneEvent>
22 22
23 23 QTCOMMERCIALCHART_BEGIN_NAMESPACE
24 24
25 25 /*!
26 26 \class QLegend
27 27 \brief part of QtCommercial chart API.
28 28
29 29 QLegend is a graphical object, whics displays legend of the chart. Legend state is updated by QChart, when
30 30 series have been changed. By default, legend is drawn by QChart, but user can set a new parent to legend and
31 31 handle the drawing manually.
32 32 User isn't supposed to create or delete legend objects, but can reference it via QChart class.
33 33
34 34 \mainclass
35 35
36 36 \sa QChart, QSeries
37 37 */
38 38
39 39 /*!
40 40 \enum QLegend::Layout
41 41
42 42 This enum describes the possible position for legend inside chart.
43 43
44 44 \value LayoutTop
45 45 \value LayoutBottom
46 46 \value LayoutLeft
47 47 \value LayoutRight
48 48 */
49 49
50 50
51 51 /*!
52 52 \fn void QLegend::clicked(QSeries* series, Qt::MouseButton button)
53 53 \brief Notifies when series has been clicked on legend \a series \a button
54 54 */
55 55
56 56 /*!
57 57 \fn void QLegend::clicked(QBarSet* barset, Qt::MouseButton button)
58 58 \brief Notifies when barset has been clicked on legend \a barset \a button
59 59 */
60 60
61 61 /*!
62 62 \fn void QLegend::clicked(QPieSlice* slice, Qt::MouseButton button)
63 63 \brief Notifies when pie slice has been clicked on legend \a slice \a button
64 64 */
65 65
66 66 /*!
67 67 Constructs the legend object and sets the parent to \a parent
68 68 */
69 69 QLegend::QLegend(QChart *chart):QGraphicsWidget(chart),
70 70 m_margin(5),
71 71 m_pos(0,0),
72 72 m_minimumSize(50,20), // TODO: magic numbers
73 73 m_maximumSize(150,100),
74 74 m_size(m_minimumSize),
75 75 m_brush(Qt::darkGray), // TODO: default should come from theme
76 76 m_alignment(QLegend::LayoutTop),
77 77 mFirstMarker(0)
78 78 {
79 79 m_scrollButtonLeft = new LegendScrollButton(LegendScrollButton::ScrollButtonIdLeft, this);
80 80 m_scrollButtonRight = new LegendScrollButton(LegendScrollButton::ScrollButtonIdRight, this);
81 81 m_scrollButtonUp = new LegendScrollButton(LegendScrollButton::ScrollButtonIdUp, this);
82 82 m_scrollButtonDown = new LegendScrollButton(LegendScrollButton::ScrollButtonIdDown, this);
83 83 setZValue(ChartPresenter::LegendZValue);
84 84 }
85 85
86 86 /*!
87 87 Paints the legend to given \a painter. Paremeters \a option and \a widget arent used.
88 88 */
89 89 void QLegend::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
90 90 {
91 91 Q_UNUSED(option)
92 92 Q_UNUSED(widget)
93 93
94 94 painter->setOpacity(opacity());
95 95 painter->setPen(m_pen);
96 96 painter->setBrush(m_brush);
97 97 // painter->drawRect(boundingRect());
98 98 }
99 99
100 100 /*!
101 101 Bounding rect of legend.
102 102 */
103 103 QRectF QLegend::boundingRect() const
104 104 {
105 105 return QRectF(m_pos,m_size);
106 106 }
107 107
108 108 /*!
109 109 Sets the \a brush of legend. Brush affects the background of legend.
110 110 */
111 111 void QLegend::setBrush(const QBrush &brush)
112 112 {
113 113 if (m_brush != brush) {
114 114 m_brush = brush;
115 115 update();
116 116 }
117 117 }
118 118
119 119 /*!
120 120 Returns the brush used by legend.
121 121 */
122 122 QBrush QLegend::brush() const
123 123 {
124 124 return m_brush;
125 125 }
126 126
127 127 /*!
128 128 Sets the \a pen of legend. Pen affects the legend borders.
129 129 */
130 130 void QLegend::setPen(const QPen &pen)
131 131 {
132 132 if (m_pen != pen) {
133 133 m_pen = pen;
134 134 update();
135 135 }
136 136 }
137 137
138 138 /*!
139 139 Returns the pen used by legend
140 140 */
141 141
142 142 QPen QLegend::pen() const
143 143 {
144 144 return m_pen;
145 145 }
146 146
147 147 /*!
148 148 Sets the \a preferred layout for legend. Legend tries to paint itself on the defined position in chart.
149 149 \sa QLegend::Layout
150 150 */
151 151 void QLegend::setAlignmnent(QLegend::Layout alignment)
152 152 {
153 153 m_alignment = alignment;
154 154 updateLayout();
155 155 }
156 156
157 157 /*!
158 158 Returns the preferred layout for legend
159 159 */
160 160 QLegend::Layout QLegend::alignment() const
161 161 {
162 162 return m_alignment;
163 163 }
164 164
165 165 /*!
166 166 Returns the maximum size of legend.
167 167 */
168 168 QSizeF QLegend::maximumSize() const
169 169 {
170 170 return m_maximumSize;
171 171 }
172 172
173 173 /*!
174 174 Sets the maximum \a size for legend. The legend can't grow bigger than this size. If there are
175 175 more series than legend can fit to this size, scroll buttons are displayed.
176 176 */
177 177 void QLegend::setMaximumSize(const QSizeF size)
178 178 {
179 179 m_maximumSize = size;
180 180 updateLayout();
181 181 }
182 182
183 183 /*!
184 184 Returns the current size of legend.
185 185 */
186 186 QSizeF QLegend::size() const
187 187 {
188 188 return m_size;
189 189 }
190 190
191 191 /*!
192 192 Sets the \a size of legend. If size is bigger than maximum size of legend, the legend is resized to the maximum size.
193 193 \sa setMmaximumSize()
194 194 */
195 195 void QLegend::setSize(const QSizeF size)
196 196 {
197 197 m_size = size;
198 198 if (m_size.width() > m_maximumSize.width()) {
199 199 m_size.setWidth(m_maximumSize.width());
200 200 }
201 201 if (m_size.height() > m_maximumSize.height()) {
202 202 m_size.setHeight(m_maximumSize.height());
203 203 }
204 204 }
205 205
206 206 /*!
207 207 Sets position of legend to \a pos
208 208 */
209 209 void QLegend::setPos(const QPointF &pos)
210 210 {
211 211 m_pos = pos;
212 212 updateLayout();
213 213 }
214 214
215 215 /*!
216 216 \internal \a series \a domain Should be called when series is added to chart.
217 217 */
218 218 void QLegend::handleSeriesAdded(QSeries *series, Domain *domain)
219 219 {
220 220 Q_UNUSED(domain)
221 221
222 createMarkers(series);
223 connectSeries(series);
222 switch (series->type())
223 {
224 case QSeries::SeriesTypeLine: {
225 QLineSeries *lineSeries = static_cast<QLineSeries *>(series);
226 appendMarkers(lineSeries);
227 break;
228 }
229 case QSeries::SeriesTypeArea: {
230 QAreaSeries *areaSeries = static_cast<QAreaSeries *>(series);
231 appendMarkers(areaSeries);
232 break;
233 }
234 case QSeries::SeriesTypeBar: {
235 QBarSeries *barSeries = static_cast<QBarSeries *>(series);
236 appendMarkers(barSeries);
237 break;
238 }
239 case QSeries::SeriesTypeStackedBar: {
240 QStackedBarSeries *stackedBarSeries = static_cast<QStackedBarSeries *>(series);
241 appendMarkers(stackedBarSeries);
242 break;
243 }
244 case QSeries::SeriesTypePercentBar: {
245 QPercentBarSeries *percentBarSeries = static_cast<QPercentBarSeries *>(series);
246 appendMarkers(percentBarSeries);
247 break;
248 }
249 case QSeries::SeriesTypeScatter: {
250 QScatterSeries *scatterSeries = static_cast<QScatterSeries *>(series);
251 appendMarkers(scatterSeries);
252 break;
253 }
254 case QSeries::SeriesTypePie: {
255 QPieSeries *pieSeries = static_cast<QPieSeries *>(series);
256 appendMarkers(pieSeries);
257 connect(pieSeries,SIGNAL(added(QList<QPieSlice*>)),this,SLOT(handleAdded(QList<QPieSlice*>)));
258 break;
259 }
260 case QSeries::SeriesTypeSpline: {
261 QSplineSeries *splineSeries = static_cast<QSplineSeries *>(series);
262 appendMarkers(splineSeries);
263 break;
264 }
265 default: {
266 qWarning()<< "QLegend::handleSeriesAdded" << series->type() << "unknown series type.";
267 break;
268 }
269 }
270
224 271 updateLayout();
225 272 }
226 273
227 274 /*!
228 275 \internal \a series Should be called when series is removed from chart.
229 276 */
230 277 void QLegend::handleSeriesRemoved(QSeries *series)
231 278 {
232 disconnectSeries(series);
233
234 if (series->type() == QSeries::SeriesTypeArea) {
235 // This is special case. Area series has upper and lower series, which each have markers
236 QAreaSeries* s = static_cast<QAreaSeries *> (series);
237 deleteMarkers(s->upperSeries());
238 deleteMarkers(s->lowerSeries());
239 } else {
279 switch (series->type())
280 {
281 case QSeries::SeriesTypeArea: {
282 QAreaSeries *areaSeries = static_cast<QAreaSeries *>(series);
283 deleteMarkers(areaSeries);
284 break;
285 }
286 case QSeries::SeriesTypePie: {
287 QPieSeries *pieSeries = static_cast<QPieSeries *>(series);
288 disconnect(pieSeries, SIGNAL(added(QList<QPieSlice *>)), this, SLOT(handleAdded(QList<QPieSlice *>)));
240 289 deleteMarkers(series);
290 break;
291 }
292 default: {
293 // All other types
294 deleteMarkers(series);
295 break;
296 }
241 297 }
242 298
243 299 updateLayout();
244 300 }
245 301
246 302 /*!
247 303 \internal \a slices Should be called when slices are added to pie chart.
248 304 */
249 305 void QLegend::handleAdded(QList<QPieSlice *> slices)
250 306 {
251 307 QPieSeries* series = static_cast<QPieSeries *> (sender());
252 308 foreach(QPieSlice* s, slices) {
253 309 LegendMarker* marker = new LegendMarker(series, s, this);
254 310 marker->setName(s->label());
255 311 marker->setBrush(s->brush());
256 312 connect(marker, SIGNAL(clicked(QPieSlice*,Qt::MouseButton)),
257 313 this, SIGNAL(clicked(QPieSlice*,Qt::MouseButton)));
258 314 connect(s, SIGNAL(changed()), marker, SLOT(changed()));
259 315 connect(s, SIGNAL(destroyed()), marker, SLOT(deleteLater()));
260 316 connect(marker, SIGNAL(destroyed()), this, SLOT(handleMarkerDestroyed()));
261 317 m_markers.append(marker);
262 318 childItems().append(marker);
263 319 }
264 320 updateLayout();
265 321 }
266 322
267 323 /*!
268 324 \internal \a slices Should be called when slices are removed from pie chart. Currently unused,
269 325 because removed slices are also deleted and we listen destroyed signal
270 326 */
271 327 void QLegend::handleRemoved(QList<QPieSlice *> slices)
272 328 {
273 329 Q_UNUSED(slices)
274 330 }
275 331
276 332
277 333 /*!
278 334 \internal Notifies legend that some marker has been removed. Sent by legend markers when destroyed
279 335 */
280 336 void QLegend::handleMarkerDestroyed()
281 337 {
282 338 LegendMarker* m = static_cast<LegendMarker *> (sender());
283 339 m_markers.removeOne(m);
284 340 updateLayout();
285 341 }
286 342
287 343 /*!
288 344 \internal \a event Handles clicked signals from scroll buttons
289 345 */
290 346 void QLegend::scrollButtonClicked(LegendScrollButton *scrollButton)
291 347 {
292 348 Q_ASSERT(scrollButton);
293 349
294 350 switch (scrollButton->id()) {
295 351 case LegendScrollButton::ScrollButtonIdLeft:
296 352 case LegendScrollButton::ScrollButtonIdUp: {
297 353 // Lower limit is same in these cases
298 354 mFirstMarker--;
299 355 checkFirstMarkerBounds();
300 356 break;
301 357 }
302 358 case LegendScrollButton::ScrollButtonIdRight:
303 359 case LegendScrollButton::ScrollButtonIdDown: {
304 360 mFirstMarker++;
305 361 checkFirstMarkerBounds();
306 362 break;
307 363 }
308 364 default: {
309 365 break;
310 366 }
311 367 }
312 368 updateLayout();
313 369 }
314 370
315 371 /*!
316 \internal Connects the \a series to legend. Legend listens changes in series, for example pie slices added / removed.
317 Not all series notify about events
318 */
319 void QLegend::connectSeries(QSeries *series)
320 {
321 // Connect relevant signals from series. Currently only pie series has interesting signals
322 // TODO: bar chart may have
323 if (series->type() == QSeries::SeriesTypePie) {
324 QPieSeries *pieSeries = static_cast<QPieSeries *>(series);
325 connect(pieSeries,SIGNAL(added(QList<QPieSlice*>)),this,SLOT(handleAdded(QList<QPieSlice*>)));
326 }
327 }
328
329 /*!
330 \internal Disconnects \a series from legend. No more status updates from series to legend.
331 */
332 void QLegend::disconnectSeries(QSeries *series)
333 {
334 if (series->type() == QSeries::SeriesTypePie) {
335 QPieSeries *pieSeries = static_cast<QPieSeries *>(series);
336 disconnect(pieSeries, SIGNAL(added(QList<QPieSlice *>)), this, SLOT(handleAdded(QList<QPieSlice *>)));
337 }
338 }
339
340 /*!
341 \internal Creates new markers for \a series. Marker contains the colored rectangle and series name.
342 With pie chart, created markers depend on pie slices.
343 With bar chart, created markers depend on bar sets.
372 \internal Helper function. Appends markers from \a series to legend.
344 373 */
345 void QLegend::createMarkers(QSeries *series)
374 void QLegend::appendMarkers(QAreaSeries* series)
346 375 {
347 switch (series->type())
348 {
349 case QSeries::SeriesTypeLine: {
350 QLineSeries *lineSeries = static_cast<QLineSeries *>(series);
351 appendMarkers(lineSeries);
352 break;
353 }
354 case QSeries::SeriesTypeArea: {
355 QAreaSeries *areaSeries = static_cast<QAreaSeries *>(series);
356 appendMarkers(areaSeries->upperSeries());
357 if(areaSeries->lowerSeries())
358 appendMarkers(areaSeries->lowerSeries());
359 break;
360 }
361 case QSeries::SeriesTypeBar: {
362 QBarSeries *barSeries = static_cast<QBarSeries *>(series);
363 appendMarkers(barSeries);
364 break;
365 }
366 case QSeries::SeriesTypeStackedBar: {
367 QStackedBarSeries *stackedBarSeries = static_cast<QStackedBarSeries *>(series);
368 appendMarkers(stackedBarSeries);
369 break;
370 }
371 case QSeries::SeriesTypePercentBar: {
372 QPercentBarSeries *percentBarSeries = static_cast<QPercentBarSeries *>(series);
373 appendMarkers(percentBarSeries);
374 break;
375 }
376 case QSeries::SeriesTypeScatter: {
377 QScatterSeries *scatterSeries = static_cast<QScatterSeries *>(series);
378 appendMarkers(scatterSeries);
379 break;
380 }
381 case QSeries::SeriesTypePie: {
382 QPieSeries *pieSeries = static_cast<QPieSeries *>(series);
383 appendMarkers(pieSeries);
384 break;
385 }
386 case QSeries::SeriesTypeSpline: {
387 QSplineSeries *splineSeries = static_cast<QSplineSeries *>(series);
388 appendMarkers(splineSeries);
389 break;
390 }
391 default: {
392 qWarning()<< "QLegend::createMarkers" << series->type() << "unknown series type.";
393 break;
394 }
395 }
376 LegendMarker* marker = new LegendMarker(series,this);
377 marker->setName(series->name());
378 marker->setPen(series->pen());
379 marker->setBrush(series->brush());
380 connect(marker, SIGNAL(clicked(QSeries *, Qt::MouseButton)), this, SIGNAL(clicked(QSeries *, Qt::MouseButton)));
381 connect(marker, SIGNAL(destroyed()), this, SLOT(handleMarkerDestroyed()));
382 connect(series,SIGNAL(updated()),marker,SLOT(changed()));
383 m_markers.append(marker);
384 childItems().append(marker);
396 385 }
397 386
398 387 /*!
399 388 \internal Helper function. Appends markers from \a series to legend.
400 389 */
401 390 void QLegend::appendMarkers(QXYSeries* series)
402 391 {
403 392 LegendMarker* marker = new LegendMarker(series,this);
404 393 marker->setName(series->name());
405 394 marker->setPen(series->pen());
406 395 marker->setBrush(series->brush());
407 396 connect(marker, SIGNAL(clicked(QSeries *, Qt::MouseButton)), this, SIGNAL(clicked(QSeries *, Qt::MouseButton)));
408 397 connect(marker, SIGNAL(destroyed()), this, SLOT(handleMarkerDestroyed()));
398 connect(series,SIGNAL(updated()),marker,SLOT(changed()));
409 399 m_markers.append(marker);
410 400 childItems().append(marker);
411 401 }
412 402
413 403 /*!
414 \internal Helper function. Appends markers from \a series to legend.
404 \internal Helper function. Appends markers from \a series to legend.
415 405 */
416 406 void QLegend::appendMarkers(QBarSeries *series)
417 407 {
418 408 foreach(QBarSet* set, series->barSets()) {
419 409 LegendMarker* marker = new LegendMarker(series, set, this);
420 410 marker->setName(set->name());
421 411 marker->setPen(set->pen());
422 412 marker->setBrush(set->brush());
423 413 connect(marker, SIGNAL(clicked(QBarSet *, Qt::MouseButton)),
424 414 this, SIGNAL(clicked(QBarSet *, Qt::MouseButton)));
425 415 connect(set, SIGNAL(valueChanged()), marker, SLOT(changed()));
426 416 connect(marker, SIGNAL(destroyed()), this, SLOT(handleMarkerDestroyed()));
427 417 m_markers.append(marker);
428 418 childItems().append(marker);
429 419 }
430 420 }
431 421
432 422 /*!
433 \internal Helper function. Appends markers from \a series to legend.
423 \internal Helper function. Appends markers from \a series to legend.
434 424 */
435 425 void QLegend::appendMarkers(QPieSeries *series)
436 426 {
437 427 foreach(QPieSlice* slice, series->slices()) {
438 428 LegendMarker* marker = new LegendMarker(series, slice, this);
439 429 marker->setName(slice->label());
440 430 marker->setPen(slice->pen());
441 431 marker->setBrush(slice->brush());
442 432 connect(marker, SIGNAL(clicked(QPieSlice *, Qt::MouseButton)),
443 433 this, SIGNAL(clicked(QPieSlice *, Qt::MouseButton)));
444 434 connect(slice, SIGNAL(changed()), marker, SLOT(changed()));
445 435 connect(slice, SIGNAL(destroyed()), marker, SLOT(deleteLater()));
446 436 connect(marker, SIGNAL(destroyed()), this, SLOT(handleMarkerDestroyed()));
447 437 m_markers.append(marker);
448 438 childItems().append(marker);
449 439 }
450 440 }
451 441
452 442 /*!
453 443 \internal Deletes all markers that are created from \a series
454 444 */
455 445 void QLegend::deleteMarkers(QSeries *series)
456 446 {
457 447 // Search all markers that belong to given series and delete them.
458 448 foreach (LegendMarker *m, m_markers) {
459 449 if (m->series() == series) {
460 450 m_markers.removeOne(m);
461 451 delete m;
462 452 }
463 453 }
464 454 }
465 455
466 456 /*!
467 457 \internal Updates layout of legend. Tries to fit as many markers as possible up to the maximum size of legend.
468 458 If items don't fit, sets the visibility of scroll buttons accordingly.
469 459 Causes legend to be resized.
470 460 */
471 461 void QLegend::updateLayout()
472 462 {
473 463 // Calculate layout for markers and text
474 464 if (m_markers.count() <= 0) {
475 465 // Nothing to do
476 466 return;
477 467 }
478 468
479 469 // Find out widest item.
480 470 QSizeF markerMaxSize = maximumMarkerSize();
481 471 checkFirstMarkerBounds();
482 472
483 473 // Use max height as scroll button size
484 474 rescaleScrollButtons(QSize(markerMaxSize.height() ,markerMaxSize.height()));
485 475
486 476 qreal totalWidth = 0;
487 477 qreal totalHeight = 0;
488 478 switch (m_alignment)
489 479 {
490 480 // Both cases organise items horizontally
491 481 case QLegend::LayoutBottom:
492 482 case QLegend::LayoutTop: {
493 483
494 484 qreal xStep = markerMaxSize.width();
495 485 qreal x = m_pos.x() + m_margin;
496 486 qreal y = m_pos.y() + m_margin;
497 487 int column = 0;
498 488 int maxColumns = 1;
499 489 qreal scrollButtonWidth = 0;
500 490
501 491 // Set correct visibility for scroll scrollbuttons
502 492 if (scrollButtonsVisible()) {
503 493 m_scrollButtonLeft->setVisible(true);
504 494 m_scrollButtonRight->setVisible(true);
505 495 // scrollbuttons visible, so add their width to total width
506 496 totalWidth += (m_scrollButtonLeft->boundingRect().width() + m_margin) * 2;
507 497 scrollButtonWidth = m_scrollButtonLeft->boundingRect().width() + m_margin;
508 498 // start position changes by scrollbutton width
509 499 x += scrollButtonWidth;
510 500 } else {
511 501 m_scrollButtonLeft->setVisible(false);
512 502 m_scrollButtonRight->setVisible(false);
513 503 }
514 504 m_scrollButtonUp->setVisible(false);
515 505 m_scrollButtonDown->setVisible(false);
516 506
517 507 for (int i=0; i < m_markers.count(); i++) {
518 508 LegendMarker *m = m_markers.at(i);
519 509 if (i < mFirstMarker) {
520 510 // Markers before first are not visible.
521 511 m->setVisible(false);
522 512 } else {
523 513 if ((x + xStep + scrollButtonWidth + m_margin) > (m_pos.x() + m_maximumSize.width())) {
524 514 // This marker would go outside legend rect.
525 515 m->setVisible(false);
526 516 } else {
527 517 // This marker is ok
528 518 m->setVisible(true);
529 519 m->setPos(x, y);
530 520 x += xStep;
531 521 column++;
532 522 }
533 523 }
534 524 maxColumns = column;
535 525 }
536 526
537 527 m_scrollButtonLeft->setPos(m_pos.x() + m_margin, y);
538 528 m_scrollButtonRight->setPos(x + m_margin, y);
539 529
540 530 totalWidth += maxColumns * markerMaxSize.width() + m_margin * 2;
541 531 totalHeight = markerMaxSize.height() + m_margin * 2;
542 532
543 533 break;
544 534 }
545 535 // Both cases organize items vertically
546 536 case QLegend::LayoutLeft:
547 537 case QLegend::LayoutRight: {
548 538 qreal yStep = markerMaxSize.height();
549 539 qreal x = m_pos.x() + m_margin;
550 540 qreal y = m_pos.y() + m_margin;
551 541 int row = 1;
552 542 int maxRows = 1;
553 543 qreal scrollButtonHeight = 0;
554 544
555 545 // Set correct visibility for scroll scrollbuttons
556 546 if (scrollButtonsVisible()) {
557 547 m_scrollButtonUp->setVisible(true);
558 548 m_scrollButtonDown->setVisible(true);
559 549 totalHeight += (m_scrollButtonUp->boundingRect().height() + m_margin) * 2; // scrollbuttons visible, so add their height to total height
560 550 scrollButtonHeight = m_scrollButtonUp->boundingRect().height();
561 551 y += scrollButtonHeight + m_margin; // start position changes by scrollbutton height
562 552 } else {
563 553 m_scrollButtonUp->setVisible(false);
564 554 m_scrollButtonDown->setVisible(false);
565 555 }
566 556 m_scrollButtonLeft->setVisible(false);
567 557 m_scrollButtonRight->setVisible(false);
568 558
569 559 for (int i=0; i < m_markers.count(); i++) {
570 560 LegendMarker* m = m_markers.at(i);
571 561 if (i < mFirstMarker) {
572 562 // Markers before first are not visible.
573 563 m->setVisible(false);
574 564 } else {
575 565 if ((y + yStep + scrollButtonHeight) > (m_pos.y() + m_maximumSize.height())) {
576 566 // This marker would go outside legend rect.
577 567 m->setVisible(false);
578 568 } else {
579 569 // This marker is ok
580 570 m->setVisible(true);
581 571 m->setPos(x, y);
582 572 y += yStep;
583 573 row++;
584 574 }
585 575 }
586 576 maxRows = row;
587 577 }
588 578
589 579 m_scrollButtonUp->setPos(m_pos.x() + m_margin, m_pos.y() + m_margin);
590 580 m_scrollButtonDown->setPos(m_pos.x() + m_margin, y + m_margin);
591 581
592 582 totalWidth += markerMaxSize.width() + m_margin * 2;
593 583 totalHeight = maxRows * markerMaxSize.height() + m_margin * 4 + scrollButtonHeight; // TODO: check this
594 584 break;
595 585 }
596 586 default: {
597 587 break;
598 588 }
599 589 }
600 590
601 591 m_size.setWidth(totalWidth);
602 592 m_size.setHeight(totalHeight);
603 593
604 594 update();
605 595 }
606 596
607 597 /*!
608 598 \internal Sets the size of scroll buttons to \a size
609 599 */
610 600 void QLegend::rescaleScrollButtons(const QSize &size)
611 601 {
612 602 QPolygonF left;
613 603 left << QPointF(size.width(), 0) << QPointF(0, size.height() / 2) << QPointF(size.width(), size.height());
614 604 QPolygonF right;
615 605 right << QPointF(0, 0) << QPointF(size.width(), size.height() / 2) << QPointF(0, size.height());
616 606 QPolygonF up;
617 607 up << QPointF(0, size.height()) << QPointF(size.width() / 2,0) << QPointF(size.width(), size.height());
618 608 QPolygonF down;
619 609 down << QPointF(0, 0) << QPointF(size.width() / 2, size.height()) << QPointF(size.width(), 0);
620 610
621 611 m_scrollButtonLeft->setPolygon(left);
622 612 m_scrollButtonRight->setPolygon(right);
623 613 m_scrollButtonUp->setPolygon(up);
624 614 m_scrollButtonDown->setPolygon(down);
625 615 }
626 616
627 617 /*!
628 618 \internal Finds out maximum size of single marker. Marker sizes depend on series names.
629 619 */
630 620 QSizeF QLegend::maximumMarkerSize()
631 621 {
632 622 QSizeF max(0,0);
633 623 foreach (LegendMarker* m, m_markers) {
634 624 if (m->boundingRect().width() > max.width())
635 625 max.setWidth(m->boundingRect().width());
636 626 if (m->boundingRect().height() > max.height())
637 627 max.setHeight(m->boundingRect().height());
638 628 }
639 629 return max;
640 630 }
641 631
642 632 /*!
643 633 \internal Checks that first marker is in acceptable bounds. Bounds range from 0 to (maximum number of markers - visible markers)
644 634 If scrollbuttons are visible, they affect the number of visible markers.
645 635 */
646 636 void QLegend::checkFirstMarkerBounds()
647 637 {
648 638 if ((m_alignment == QLegend::LayoutLeft) || (m_alignment == QLegend::LayoutRight)) {
649 639 // Bounds limited by height.
650 640 int max;
651 641 if (scrollButtonsVisible()) {
652 642 max = (m_maximumSize.height() - m_scrollButtonLeft->boundingRect().height() * 2 - m_margin * 4) / maximumMarkerSize().height();
653 643 } else {
654 644 max = m_maximumSize.height() / maximumMarkerSize().height();
655 645 }
656 646
657 647 if (mFirstMarker > m_markers.count() - max)
658 648 mFirstMarker = m_markers.count() - max;
659 649 } else {
660 650 // Bounds limited by width
661 651 int max;
662 652 if (scrollButtonsVisible()) {
663 653 max = (m_maximumSize.width() - m_scrollButtonLeft->boundingRect().width() * 2 - m_margin*4) / maximumMarkerSize().width();
664 654 } else {
665 655 max = m_maximumSize.width() / maximumMarkerSize().width();
666 656 }
667 657
668 658 if (mFirstMarker > m_markers.count() - max)
669 659 mFirstMarker = m_markers.count() - max;
670 660 }
671 661
672 662 if (mFirstMarker < 0)
673 663 mFirstMarker = 0;
674 664 }
675 665
676 666 /*!
677 667 \internal Helper function. Visibility of scroll buttons isn't quite obvious, so helper function clarifies the logic.
678 668 */
679 669 bool QLegend::scrollButtonsVisible()
680 670 {
681 671 // Just a helper to clarify, what the magic below means :)
682 672 if ((m_alignment == QLegend::LayoutTop) || (m_alignment == QLegend::LayoutBottom)) {
683 673 return (maximumMarkerSize().width() * m_markers.count() + m_margin * 2 > m_maximumSize.width());
684 674 } else if ((m_alignment == QLegend::LayoutLeft) || (m_alignment == QLegend::LayoutRight)) {
685 675 return (maximumMarkerSize().height() * m_markers.count() + m_margin * 2 > m_maximumSize.height());
686 676 }
687 677
688 678 return (maximumMarkerSize().height() * m_markers.count() + m_margin * 2 > m_maximumSize.height());
689 679 }
690 680
691 681 #include "moc_qlegend.cpp"
692 682
693 683 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,116 +1,115
1 1 #ifndef QLEGEND_H
2 2 #define QLEGEND_H
3 3
4 4 #include <QChartGlobal>
5 5 #include <QGraphicsWidget>
6 6 #include <QPen>
7 7 #include <QBrush>
8 8
9 9 QTCOMMERCIALCHART_BEGIN_NAMESPACE
10 10
11 11 class Domain;
12 12 class LegendMarker;
13 13 class QPieSlice;
14 14 class QXYSeries;
15 15 class QBarSet;
16 16 class QBarSeries;
17 17 class QPieSeries;
18 class QAreaSeries;
18 19 class LegendScrollButton;
19 20 class QSeries;
20 21 class QChart;
21 22
22 23 // TODO: This as widget
23 24 class QTCOMMERCIALCHART_EXPORT QLegend : public QGraphicsWidget
24 25 {
25 26 Q_OBJECT
26 27 public:
27 28
28 29 // We only support these alignments (for now)
29 30 enum Layout {
30 31 LayoutTop = Qt::AlignTop,
31 32 LayoutBottom = Qt::AlignBottom,
32 33 LayoutLeft = Qt::AlignLeft,
33 34 LayoutRight = Qt::AlignRight
34 35 };
35 36 private:
36 37 explicit QLegend(QChart *chart);
37 38
38 39 public:
39 40 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
40 41 QRectF boundingRect() const;
41 42
42 43 void setBrush(const QBrush &brush);
43 44 QBrush brush() const;
44 45
45 46 void setPen(const QPen &pen);
46 47 QPen pen() const;
47 48
48 49 void setAlignmnent(QLegend::Layout alignment);
49 50 QLegend::Layout alignment() const;
50 51
51 52 QSizeF maximumSize() const;
52 53 void setMaximumSize(const QSizeF size);
53 54
54 55 QSizeF size() const;
55 56 void setSize(const QSizeF size);
56 57 void setPos(const QPointF &pos);
57 58
58 59 void scrollButtonClicked(LegendScrollButton *scrollButton);
59 60
60 61 Q_SIGNALS:
61 62 // for interactions.
62 63 void clicked(QSeries *series, Qt::MouseButton button);
63 64 void clicked(QBarSet *barset, Qt::MouseButton button);
64 65 void clicked(QPieSlice *slice, Qt::MouseButton button);
65 66
66 67 public Q_SLOTS:
67 68 // PIMPL --->
68 69 void handleSeriesAdded(QSeries *series, Domain *domain);
69 70 void handleSeriesRemoved(QSeries *series);
70 71 void handleAdded(QList<QPieSlice *> slices);
71 72 void handleRemoved(QList<QPieSlice *> slices);
72 73 void handleMarkerDestroyed();
73 74
74 75 // PIMPL <---
75 76
76 77 private:
77 78 // PIMPL --->
78 void connectSeries(QSeries *series);
79 void disconnectSeries(QSeries *series);
80 void createMarkers(QSeries *series);
81 void appendMarkers(QXYSeries *series); // All line series are derived from QXYSeries, so this works for now
79 void appendMarkers(QAreaSeries *series);
80 void appendMarkers(QXYSeries *series);
82 81 void appendMarkers(QBarSeries *series);
83 82 void appendMarkers(QPieSeries *series);
84 83 void deleteMarkers(QSeries *series);
85 84 void updateLayout();
86 85 void rescaleScrollButtons(const QSize &size);
87 86 QSizeF maximumMarkerSize();
88 87 void checkFirstMarkerBounds();
89 88 bool scrollButtonsVisible();
90 89
91 90 qreal m_margin;
92 91 QPointF m_pos;
93 92 QSizeF m_minimumSize;
94 93 QSizeF m_maximumSize;
95 94 QSizeF m_size;
96 95
97 96 QList<LegendMarker *> m_markers;
98 97
99 98 QBrush m_brush;
100 99 QPen m_pen;
101 100 QLegend::Layout m_alignment;
102 101
103 102 int mFirstMarker;
104 103
105 104 LegendScrollButton *m_scrollButtonLeft;
106 105 LegendScrollButton *m_scrollButtonRight;
107 106 LegendScrollButton *m_scrollButtonUp;
108 107 LegendScrollButton *m_scrollButtonDown;
109 108
110 109 friend class QChart;
111 110 // <--- PIMPL
112 111 };
113 112
114 113 QTCOMMERCIALCHART_END_NAMESPACE
115 114
116 115 #endif // QLEGEND_H
General Comments 0
You need to be logged in to leave comments. Login now