##// END OF EJS Templates
background to legend, theme applies
sauimone -
r540:7d8a0757e05d
parent child
Show More
@@ -1,156 +1,153
1 1 #include <QtGui/QApplication>
2 2 #include <QMainWindow>
3 3 #include <qchartglobal.h>
4 4 #include <qchartview.h>
5 5 #include <qstackedbarseries.h>
6 6 #include <qbarset.h>
7 7 #include <qchartaxis.h>
8 8 #include <qlegend.h>
9 9 #include <QStringList>
10 10 #include <QDebug>
11 11
12 12 QTCOMMERCIALCHART_USE_NAMESPACE
13 13
14 14 //! [1]
15 15 class DrilldownBarSeries : public QStackedBarSeries
16 16 {
17 17 Q_OBJECT
18 18 public:
19 19 DrilldownBarSeries(QStringList categories, QObject *parent = 0) : QStackedBarSeries(categories,parent) {}
20 20
21 21 void mapDrilldownSeries(QString category, DrilldownBarSeries* drilldownSeries)
22 22 {
23 23 mDrilldownSeries[category] = drilldownSeries;
24 24 }
25 25
26 26 DrilldownBarSeries* drilldownSeries(QString category)
27 27 {
28 28 return mDrilldownSeries[category];
29 29 }
30 30
31 31 public Q_SLOTS:
32 32
33 33 private:
34 34
35 35 QMap<QString, DrilldownBarSeries*> mDrilldownSeries;
36 36 };
37 37 //! [1]
38 38
39 39 //! [2]
40 40 class DrilldownChart : public QChartView
41 41 {
42 42 Q_OBJECT
43 43 public:
44 44 explicit DrilldownChart(QWidget *parent = 0) : QChartView(parent), m_currentSeries(0) {}
45 45
46 46 void changeSeries(QSeries* series)
47 47 {
48 48 if (m_currentSeries)
49 49 removeSeries(m_currentSeries);
50 50 m_currentSeries = series;
51 51 addSeries(series);
52 52 setChartTitle(series->title());
53 53 }
54 54
55 55 public Q_SLOTS:
56 56 void handleRightClick(QBarSet *barset, QString category)
57 57 {
58 58 // qDebug() << "DrilldownChart::handleRightClick" << barset->name() << category;
59 59 DrilldownBarSeries* series = static_cast<DrilldownBarSeries*> (sender());
60 60 changeSeries(series->drilldownSeries(category));
61 61 }
62 62
63 63 private:
64 64 QSeries* m_currentSeries;
65 65 };
66 66 //! [2]
67 67
68 68 int main(int argc, char *argv[])
69 69 {
70 70 QApplication a(argc, argv);
71 71 QMainWindow window;
72 72
73 73 DrilldownChart* drilldownChart = new DrilldownChart(&window);
74 74 drilldownChart->setChartTheme(QChart::ChartThemeIcy);
75 75
76 76 //! [3]
77 77 // Define categories
78 78 QStringList months;
79 79 months << "May" << "Jun" << "Jul" << "Aug" << "Sep";
80 80 QStringList weeks;
81 81 weeks << "week 1" << "week 2" << "week 3" << "week 4";
82 82 QStringList plants;
83 83 plants << "Habanero" << "Lemon Drop" << "Starfish" << "Aji Amarillo";
84 84 //! [3]
85 85
86 86 //! [4]
87 87 // Create drilldown structure
88 88 DrilldownBarSeries* seasonSeries = new DrilldownBarSeries(months, drilldownChart);
89 89 seasonSeries->setTitle("Crop by month - Season");
90 90
91 91 // Each month in season series has drilldown series for weekly data
92 92 foreach (QString month, months) {
93 93
94 94 // Create drilldown series for every week
95 95 DrilldownBarSeries* weeklySeries = new DrilldownBarSeries(weeks, drilldownChart);
96 96 seasonSeries->mapDrilldownSeries(month, weeklySeries);
97 97
98 98 // Drilling down from weekly data brings us back to season data.
99 99 foreach (QString week, weeks) {
100 100 weeklySeries->mapDrilldownSeries(week, seasonSeries);
101 101 weeklySeries->setTitle(QString("Crop by week - " + month));
102 102 }
103 103
104 104 // Use right click signal to implement drilldown
105 105 QObject::connect(weeklySeries,SIGNAL(rightClicked(QBarSet*,QString)),drilldownChart,SLOT(handleRightClick(QBarSet*,QString)));
106 106 }
107 107
108 108 // Enable drilldown from season series using right click.
109 109 QObject::connect(seasonSeries,SIGNAL(rightClicked(QBarSet*,QString)),drilldownChart,SLOT(handleRightClick(QBarSet*,QString)));
110 110 //! [4]
111 111
112 112 //! [5]
113 113 // Fill monthly and weekly series with data
114 114 foreach (QString plant, plants) {
115 115 QBarSet* monthlyCrop = new QBarSet(plant);
116 116 foreach (QString month, months) {
117 117 QBarSet* weeklyCrop = new QBarSet(plant);
118 118 foreach (QString week, weeks ) {
119 119 *weeklyCrop << (qrand() % 20);
120 120 }
121 121 // Get the drilldown series from season series and add crop to it.
122 122 seasonSeries->drilldownSeries(month)->addBarSet(weeklyCrop);
123 123 seasonSeries->drilldownSeries(month)->setToolTipEnabled(true);
124 124 *monthlyCrop << weeklyCrop->total();
125 125
126 126 QObject::connect(weeklyCrop,SIGNAL(clicked(QString)),weeklyCrop,SIGNAL(toggleFloatingValues()));
127 127 }
128 128 seasonSeries->addBarSet(monthlyCrop);
129 129 QObject::connect(monthlyCrop,SIGNAL(clicked(QString)),monthlyCrop,SIGNAL(toggleFloatingValues()));
130 130 }
131 131 //! [5]
132 132
133 133 seasonSeries->setToolTipEnabled(true);
134 134
135 135 //! [6]
136 136 // Show season series in initial view
137 137 drilldownChart->changeSeries(seasonSeries);
138 138 drilldownChart->setChartTitle(seasonSeries->title());
139 139 //! [6]
140 140
141 // Disable axis, since they don't really apply to bar chart
142 // drilldownChart->axisX()->setAxisVisible(false);
143 141 drilldownChart->axisX()->setGridLineVisible(false);
144 // drilldownChart->axisX()->setLabelsVisible(false);
145 142
146 143 QLegend* l = drilldownChart->legend();
147 l->handleGeometryChanged(QRectF(20,20,100,100));
144 l->handleGeometryChanged(QRectF(50,270,300,20));
148 145
149 146 window.setCentralWidget(drilldownChart);
150 147 window.resize(400, 300);
151 148 window.show();
152 149
153 150 return a.exec();
154 151 }
155 152
156 153 #include "main.moc"
@@ -1,389 +1,390
1 1 #include "qchart.h"
2 2 #include "qchartaxis.h"
3 3 #include "chartpresenter_p.h"
4 4 #include "chartdataset_p.h"
5 5 #include "charttheme_p.h"
6 6 #include "chartanimator_p.h"
7 7 //series
8 8 #include "qbarseries.h"
9 9 #include "qstackedbarseries.h"
10 10 #include "qpercentbarseries.h"
11 11 #include "qlineseries.h"
12 12 #include "qareaseries.h"
13 13 #include "qpieseries.h"
14 14 #include "qscatterseries.h"
15 15 #include "qsplineseries.h"
16 16 //items
17 17 #include "axisitem_p.h"
18 18 #include "areachartitem_p.h"
19 19 #include "barpresenter_p.h"
20 20 #include "stackedbarpresenter_p.h"
21 21 #include "percentbarpresenter_p.h"
22 22 #include "linechartitem_p.h"
23 23 #include "piepresenter_p.h"
24 24 #include "scatterchartitem_p.h"
25 25 #include "splinechartitem_p.h"
26 26
27 27 QTCOMMERCIALCHART_BEGIN_NAMESPACE
28 28
29 29 ChartPresenter::ChartPresenter(QChart* chart,ChartDataSet* dataset):QObject(chart),
30 30 m_chart(chart),
31 31 m_animator(0),
32 32 m_dataset(dataset),
33 33 m_chartTheme(0),
34 34 m_zoomIndex(0),
35 35 m_marginSize(0),
36 36 m_rect(QRectF(QPoint(0,0),m_chart->size())),
37 37 m_options(QChart::NoAnimation)
38 38 {
39 39 createConnections();
40 40 setChartTheme(QChart::ChartThemeDefault);
41 41 }
42 42
43 43 ChartPresenter::~ChartPresenter()
44 44 {
45 45 delete m_chartTheme;
46 46 }
47 47
48 48 void ChartPresenter::createConnections()
49 49 {
50 50 QObject::connect(m_chart,SIGNAL(geometryChanged()),this,SLOT(handleGeometryChanged()));
51 51 QObject::connect(m_dataset,SIGNAL(seriesAdded(QSeries*,Domain*)),this,SLOT(handleSeriesAdded(QSeries*,Domain*)));
52 52 QObject::connect(m_dataset,SIGNAL(seriesRemoved(QSeries*)),this,SLOT(handleSeriesRemoved(QSeries*)));
53 53 QObject::connect(m_dataset,SIGNAL(axisAdded(QChartAxis*,Domain*)),this,SLOT(handleAxisAdded(QChartAxis*,Domain*)));
54 54 QObject::connect(m_dataset,SIGNAL(axisRemoved(QChartAxis*)),this,SLOT(handleAxisRemoved(QChartAxis*)));
55 55 }
56 56
57 57
58 58 QRectF ChartPresenter::geometry() const
59 59 {
60 60 return m_rect;
61 61 }
62 62
63 63 void ChartPresenter::handleGeometryChanged()
64 64 {
65 65 QRectF rect(QPoint(0,0),m_chart->size());
66 66 rect.adjust(m_marginSize,m_marginSize, -m_marginSize, -m_marginSize);
67 67
68 68 //rewrite zoom stack
69 69 for(int i=0;i<m_zoomStack.count();i++){
70 70 QRectF r = m_zoomStack[i];
71 71 qreal w = rect.width()/m_rect.width();
72 72 qreal h = rect.height()/m_rect.height();
73 73 QPointF tl = r.topLeft();
74 74 tl.setX(tl.x()*w);
75 75 tl.setY(tl.y()*h);
76 76 QPointF br = r.bottomRight();
77 77 br.setX(br.x()*w);
78 78 br.setY(br.y()*h);
79 79 r.setTopLeft(tl);
80 80 r.setBottomRight(br);
81 81 m_zoomStack[i]=r;
82 82 }
83 83
84 84 m_rect = rect;
85 85 Q_ASSERT(m_rect.isValid());
86 86 emit geometryChanged(m_rect);
87 87 }
88 88
89 89 int ChartPresenter::margin() const
90 90 {
91 91 return m_marginSize;
92 92 }
93 93
94 94 void ChartPresenter::setMargin(int margin)
95 95 {
96 96 m_marginSize = margin;
97 97 }
98 98
99 99 void ChartPresenter::handleAxisAdded(QChartAxis* axis,Domain* domain)
100 100 {
101 101 AxisItem* item = new AxisItem(axis,this,axis==m_dataset->axisX()?AxisItem::X_AXIS : AxisItem::Y_AXIS,m_chart);
102 102
103 103 if(m_options.testFlag(QChart::GridAxisAnimations)){
104 104 m_animator->addAnimation(item);
105 105 }
106 106
107 107 if(axis==m_dataset->axisX()){
108 108 QObject::connect(domain,SIGNAL(rangeXChanged(qreal,qreal,int)),item,SLOT(handleRangeChanged(qreal,qreal,int)));
109 109 //initialize
110 110 item->handleRangeChanged(domain->minX(),domain->maxX(),domain->tickXCount());
111 111 }
112 112 else{
113 113 QObject::connect(domain,SIGNAL(rangeYChanged(qreal,qreal,int)),item,SLOT(handleRangeChanged(qreal,qreal,int)));
114 114 //initialize
115 115 item->handleRangeChanged(domain->minY(),domain->maxY(),domain->tickYCount());
116 116 }
117 117
118 118 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),item,SLOT(handleGeometryChanged(const QRectF&)));
119 119 //initialize
120 120 item->handleGeometryChanged(m_rect);
121 121 m_chartTheme->decorate(axis,item);
122 122 m_axisItems.insert(axis,item);
123 123
124 124 }
125 125
126 126 void ChartPresenter::handleAxisRemoved(QChartAxis* axis)
127 127 {
128 128 AxisItem* item = m_axisItems.take(axis);
129 129 Q_ASSERT(item);
130 130 if(m_animator) m_animator->removeAnimation(item);
131 131 delete item;
132 132 }
133 133
134 134
135 135 void ChartPresenter::handleSeriesAdded(QSeries* series,Domain* domain)
136 136 {
137 137 ChartItem *item = 0 ;
138 138
139 139 switch(series->type())
140 140 {
141 141 case QSeries::SeriesTypeLine: {
142 142
143 143 QLineSeries* lineSeries = static_cast<QLineSeries*>(series);
144 144 LineChartItem* line = new LineChartItem(lineSeries,m_chart);
145 145 if(m_options.testFlag(QChart::SeriesAnimations)) {
146 146 m_animator->addAnimation(line);
147 147 }
148 148 m_chartTheme->decorate(line, lineSeries, m_dataset->seriesIndex(series));
149 149 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),line,SLOT(handleGeometryChanged(const QRectF&)));
150 150 QObject::connect(domain,SIGNAL(domainChanged(qreal,qreal,qreal,qreal)),line,SLOT(handleDomainChanged(qreal,qreal,qreal,qreal)));
151 151 item = line;
152 152 break;
153 153 }
154 154
155 155 case QSeries::SeriesTypeArea: {
156 156
157 157 QAreaSeries* areaSeries = static_cast<QAreaSeries*>(series);
158 158 AreaChartItem* area = new AreaChartItem(areaSeries,m_chart);
159 159 if(m_options.testFlag(QChart::SeriesAnimations)) {
160 160 // m_animator->addAnimation(area);
161 161 }
162 162 m_chartTheme->decorate(area, areaSeries, m_dataset->seriesIndex(series));
163 163 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),area,SLOT(handleGeometryChanged(const QRectF&)));
164 164 QObject::connect(domain,SIGNAL(domainChanged(qreal,qreal,qreal,qreal)),area,SLOT(handleDomainChanged(qreal,qreal,qreal,qreal)));
165 165 item=area;
166 166 break;
167 167 }
168 168
169 169 case QSeries::SeriesTypeBar: {
170 170 QBarSeries* barSeries = static_cast<QBarSeries*>(series);
171 171 BarPresenter* bar = new BarPresenter(barSeries,m_chart);
172 172 if(m_options.testFlag(QChart::SeriesAnimations)) {
173 173 // m_animator->addAnimation(bar);
174 174 }
175 175 m_chartTheme->decorate(bar, barSeries, m_dataset->seriesIndex(barSeries));
176 176 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),bar,SLOT(handleGeometryChanged(const QRectF&)));
177 177 QObject::connect(domain,SIGNAL(domainChanged(qreal,qreal,qreal,qreal)),bar,SLOT(handleDomainChanged(qreal,qreal,qreal,qreal)));
178 178 item=bar;
179 179 break;
180 180 }
181 181
182 182 case QSeries::SeriesTypeStackedBar: {
183 183 QStackedBarSeries* stackedBarSeries = static_cast<QStackedBarSeries*>(series);
184 184 StackedBarPresenter* bar = new StackedBarPresenter(stackedBarSeries,m_chart);
185 185 if(m_options.testFlag(QChart::SeriesAnimations)) {
186 186 // m_animator->addAnimation(bar);
187 187 }
188 188 m_chartTheme->decorate(bar, stackedBarSeries, m_dataset->seriesIndex(stackedBarSeries));
189 189 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),bar,SLOT(handleGeometryChanged(const QRectF&)));
190 190 QObject::connect(domain,SIGNAL(domainChanged(qreal,qreal,qreal,qreal)),bar,SLOT(handleDomainChanged(qreal,qreal,qreal,qreal)));
191 191 item=bar;
192 192 break;
193 193 }
194 194
195 195 case QSeries::SeriesTypePercentBar: {
196 196 QPercentBarSeries* percentBarSeries = static_cast<QPercentBarSeries*>(series);
197 197 PercentBarPresenter* bar = new PercentBarPresenter(percentBarSeries,m_chart);
198 198 if(m_options.testFlag(QChart::SeriesAnimations)) {
199 199 // m_animator->addAnimation(bar);
200 200 }
201 201 m_chartTheme->decorate(bar, percentBarSeries, m_dataset->seriesIndex(percentBarSeries));
202 202 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),bar,SLOT(handleGeometryChanged(const QRectF&)));
203 203 QObject::connect(domain,SIGNAL(domainChanged(qreal,qreal,qreal,qreal)),bar,SLOT(handleDomainChanged(qreal,qreal,qreal,qreal)));
204 204 item=bar;
205 205 break;
206 206 }
207 207
208 208 case QSeries::SeriesTypeScatter: {
209 209 QScatterSeries *scatterSeries = static_cast<QScatterSeries *>(series);
210 210 ScatterChartItem *scatter = new ScatterChartItem(scatterSeries, m_chart);
211 211 if(m_options.testFlag(QChart::SeriesAnimations)) {
212 212 m_animator->addAnimation(scatter);
213 213 }
214 214 m_chartTheme->decorate(scatter, scatterSeries, m_dataset->seriesIndex(series));
215 215 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),scatter,SLOT(handleGeometryChanged(const QRectF&)));
216 216 QObject::connect(domain,SIGNAL(domainChanged(qreal,qreal,qreal,qreal)),scatter,SLOT(handleDomainChanged(qreal,qreal,qreal,qreal)));
217 217 item = scatter;
218 218 break;
219 219 }
220 220
221 221 case QSeries::SeriesTypePie: {
222 222 QPieSeries *pieSeries = static_cast<QPieSeries *>(series);
223 223 PiePresenter* pie = new PiePresenter(m_chart, pieSeries);
224 224 if(m_options.testFlag(QChart::SeriesAnimations)) {
225 225 // m_animator->addAnimation(pie);
226 226 }
227 227 m_chartTheme->decorate(pie, pieSeries, m_dataset->seriesIndex(series));
228 228 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),pie,SLOT(handleGeometryChanged(const QRectF&)));
229 229 QObject::connect(domain,SIGNAL(domainChanged(qreal,qreal,qreal,qreal)),pie,SLOT(handleDomainChanged(qreal,qreal,qreal,qreal)));
230 230 // Hide all from background when there is only piechart
231 231 // TODO: refactor this ugly code... should be one setting for this
232 232 if (m_chartItems.count() == 0) {
233 233 m_chart->axisX()->hide();
234 234 m_chart->axisY()->hide();
235 235 m_chart->setChartBackgroundBrush(Qt::transparent);
236 236 }
237 237 item=pie;
238 238 break;
239 239 }
240 240
241 241 case QSeries::SeriesTypeSpline: {
242 242 QSplineSeries* splineSeries = static_cast<QSplineSeries*>(series);
243 243 SplineChartItem* spline = new SplineChartItem(splineSeries, m_chart);
244 244 if(m_options.testFlag(QChart::SeriesAnimations)) {
245 245 m_animator->addAnimation(spline);
246 246 }
247 247 m_chartTheme->decorate(spline, splineSeries, m_dataset->seriesIndex(series));
248 248 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),spline,SLOT(handleGeometryChanged(const QRectF&)));
249 249 QObject::connect(domain,SIGNAL(domainChanged(qreal,qreal,qreal,qreal)),spline,SLOT(handleDomainChanged(qreal,qreal,qreal,qreal)));
250 250 item=spline;
251 251 break;
252 252 }
253 253 default: {
254 254 qDebug()<< "Series type" << series->type() << "not implemented.";
255 255 break;
256 256 }
257 257 }
258 258
259 259 //initialize
260 260 item->handleDomainChanged(domain->minX(),domain->maxX(),domain->minY(),domain->maxY());
261 261 if(m_rect.isValid()) item->handleGeometryChanged(m_rect);
262 262 m_chartItems.insert(series,item);
263 263 zoomReset();
264 264 }
265 265
266 266 void ChartPresenter::handleSeriesRemoved(QSeries* series)
267 267 {
268 268 ChartItem* item = m_chartItems.take(series);
269 269 Q_ASSERT(item);
270 270 if(m_animator) m_animator->removeAnimation(item);
271 271 delete item;
272 272 }
273 273
274 274 void ChartPresenter::setChartTheme(QChart::ChartTheme theme)
275 275 {
276 276 if(m_chartTheme && m_chartTheme->id() == theme) return;
277 277 delete m_chartTheme;
278 278 m_chartTheme = ChartTheme::createTheme(theme);
279 279 m_chartTheme->decorate(m_chart);
280 m_chartTheme->decorate(m_chart->legend());
280 281 resetAllElements();
281 282 }
282 283
283 284 QChart::ChartTheme ChartPresenter::chartTheme()
284 285 {
285 286 return m_chartTheme->id();
286 287 }
287 288
288 289 void ChartPresenter::setAnimationOptions(QChart::AnimationOptions options)
289 290 {
290 291 if(m_options!=options) {
291 292
292 293 m_options=options;
293 294
294 295 if(m_options!=QChart::NoAnimation && !m_animator) {
295 296 m_animator= new ChartAnimator(this);
296 297
297 298 }
298 299 resetAllElements();
299 300 }
300 301
301 302 }
302 303
303 304 void ChartPresenter::resetAllElements()
304 305 {
305 306 QList<QChartAxis*> axisList = m_axisItems.uniqueKeys();
306 307 QList<QSeries*> seriesList = m_chartItems.uniqueKeys();
307 308
308 309 foreach(QChartAxis* axis, axisList) {
309 310 handleAxisRemoved(axis);
310 311 handleAxisAdded(axis,m_dataset->domain(axis));
311 312 }
312 313 foreach(QSeries* series, seriesList) {
313 314 handleSeriesRemoved(series);
314 315 handleSeriesAdded(series,m_dataset->domain(series));
315 316 }
316 317 }
317 318
318 319 void ChartPresenter::zoomIn()
319 320 {
320 321 QRectF rect = geometry();
321 322 rect.setWidth(rect.width()/2);
322 323 rect.setHeight(rect.height()/2);
323 324 rect.moveCenter(geometry().center());
324 325 zoomIn(rect);
325 326 }
326 327
327 328 void ChartPresenter::zoomIn(const QRectF& rect)
328 329 {
329 330 QRectF r = rect.normalized();
330 331 r.translate(-m_marginSize, -m_marginSize);
331 332 if(m_animator) {
332 333
333 334 QPointF point(r.center().x()/geometry().width(),r.center().y()/geometry().height());
334 335 m_animator->setState(ChartAnimator::ZoomInState,point);
335 336 }
336 337 m_dataset->zoomInDomain(r,geometry().size());
337 338 m_zoomStack<<r;
338 339 m_zoomIndex++;
339 340 if(m_animator) {
340 341 m_animator->setState(ChartAnimator::ShowState);
341 342 }
342 343 }
343 344
344 345 void ChartPresenter::zoomOut()
345 346 {
346 347 if(m_zoomIndex==0) return;
347 348 if(m_animator)
348 349 {
349 350 m_animator->setState(ChartAnimator::ZoomOutState);
350 351 }
351 352 m_dataset->zoomOutDomain(m_zoomStack[m_zoomIndex-1],geometry().size());
352 353 m_zoomIndex--;
353 354 m_zoomStack.resize(m_zoomIndex);
354 355 if(m_animator){
355 356 m_animator->setState(ChartAnimator::ShowState);
356 357 }
357 358 }
358 359
359 360 void ChartPresenter::zoomReset()
360 361 {
361 362 m_zoomIndex=0;
362 363 m_zoomStack.resize(m_zoomIndex);
363 364 }
364 365
365 366 void ChartPresenter::scroll(int dx,int dy)
366 367 {
367 368 if(m_animator){
368 369 if(dx<0) m_animator->setState(ChartAnimator::ScrollLeftState,QPointF());
369 370 if(dx>0) m_animator->setState(ChartAnimator::ScrollRightState,QPointF());
370 371 if(dy<0) m_animator->setState(ChartAnimator::ScrollUpState,QPointF());
371 372 if(dy>0) m_animator->setState(ChartAnimator::ScrollDownState,QPointF());
372 373 }
373 374
374 375 m_dataset->scrollDomain(dx,dy,geometry().size());
375 376
376 377 if(m_animator){
377 378 m_animator->setState(ChartAnimator::ShowState);
378 379 }
379 380 }
380 381
381 382 QChart::AnimationOptions ChartPresenter::animationOptions() const
382 383 {
383 384 return m_options;
384 385 }
385 386
386 387
387 388 #include "moc_chartpresenter_p.cpp"
388 389
389 390 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,84 +1,85
1 1 #ifndef CHARTPRESENTER_H_
2 2 #define CHARTPRESENTER_H_
3 3
4 4 #include "qchartglobal.h"
5 5 #include "qchart.h" //becouse of QChart::ChartThemeId //TODO
6 6 #include "qchartaxis.h"
7 7 #include <QRectF>
8 8
9 9 QTCOMMERCIALCHART_BEGIN_NAMESPACE
10 10
11 11 class ChartItem;
12 12 class QSeries;
13 13 class ChartDataSet;
14 14 class Domain;
15 15 class AxisItem;
16 16 class ChartTheme;
17 17 class ChartAnimator;
18 18
19 19 class ChartPresenter: public QObject
20 20 {
21 21 Q_OBJECT
22 22 public:
23 23 enum ZValues {
24 24 BackgroundZValue = -1,
25 25 ShadesZValue,
26 26 GridZValue,
27 27 AxisZValue,
28 28 LineChartZValue,
29 29 ScatterSeriesZValue,
30 PieSeriesZValue
30 PieSeriesZValue,
31 LegendZValue
31 32 };
32 33
33 34 ChartPresenter(QChart* chart,ChartDataSet *dataset);
34 35 virtual ~ChartPresenter();
35 36
36 37 void setMargin(int margin);
37 38 int margin() const;
38 39
39 40 QRectF geometry() const;
40 41 ChartAnimator* animator() const {return m_animator;};
41 42
42 43 void setChartTheme(QChart::ChartTheme theme);
43 44 QChart::ChartTheme chartTheme();
44 45
45 46 void setAnimationOptions(QChart::AnimationOptions options);
46 47 QChart::AnimationOptions animationOptions() const;
47 48
48 49 void zoomIn();
49 50 void zoomIn(const QRectF& rect);
50 51 void zoomOut();
51 52 void zoomReset();
52 53 void scroll(int dx,int dy);
53 54 private:
54 55 void createConnections();
55 56 void resetAllElements();
56 57
57 58 public slots:
58 59 void handleSeriesAdded(QSeries* series,Domain* domain);
59 60 void handleSeriesRemoved(QSeries* series);
60 61 void handleAxisAdded(QChartAxis* axis,Domain* domain);
61 62 void handleAxisRemoved(QChartAxis* axis);
62 63 void handleGeometryChanged();
63 64
64 65 signals:
65 66 void geometryChanged(const QRectF& rect);
66 67
67 68 private:
68 69 QChart* m_chart;
69 70 ChartAnimator* m_animator;
70 71 ChartDataSet* m_dataset;
71 72 ChartTheme *m_chartTheme;
72 73 int m_zoomIndex;
73 74 int m_marginSize;
74 75 QMap<QSeries*,ChartItem*> m_chartItems;
75 76 QMap<QChartAxis*,AxisItem*> m_axisItems;
76 77 QVector<QRectF> m_zoomStack;
77 78 QRectF m_rect;
78 79 QChart::AnimationOptions m_options;
79 80
80 81 };
81 82
82 83 QTCOMMERCIALCHART_END_NAMESPACE
83 84
84 85 #endif /* CHARTPRESENTER_H_ */
@@ -1,304 +1,310
1 1 #include "charttheme_p.h"
2 2 #include "qchart.h"
3 #include "qlegend.h"
3 4 #include "qchartaxis.h"
4 5 #include <QTime>
5 6
6 7 //series
7 8 #include "qbarset.h"
8 9 #include "qbarseries.h"
9 10 #include "qstackedbarseries.h"
10 11 #include "qpercentbarseries.h"
11 12 #include "qlineseries.h"
12 13 #include "qareaseries.h"
13 14 #include "qscatterseries.h"
14 15 #include "qpieseries.h"
15 16 #include "qpieslice.h"
16 17 #include "qsplineseries.h"
17 18
18 19 //items
19 20 #include "axisitem_p.h"
20 21 #include "barpresenter_p.h"
21 22 #include "stackedbarpresenter_p.h"
22 23 #include "percentbarpresenter_p.h"
23 24 #include "linechartitem_p.h"
24 25 #include "areachartitem_p.h"
25 26 #include "scatterchartitem_p.h"
26 27 #include "piepresenter_p.h"
27 28 #include "splinechartitem_p.h"
28 29
29 30 //themes
30 31 #include "chartthemedefault_p.h"
31 32 #include "chartthemevanilla_p.h"
32 33 #include "chartthemeicy_p.h"
33 34 #include "chartthemegrayscale_p.h"
34 35 #include "chartthemescientific_p.h"
35 36
36 37
37 38 QTCOMMERCIALCHART_BEGIN_NAMESPACE
38 39
39 40 ChartTheme::ChartTheme(QChart::ChartTheme id)
40 41 {
41 42 m_id = id;
42 43 qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
43 44 }
44 45
45 46
46 47 ChartTheme* ChartTheme::createTheme(QChart::ChartTheme theme)
47 48 {
48 49 switch(theme) {
49 50 case QChart::ChartThemeVanilla:
50 51 return new ChartThemeVanilla();
51 52 case QChart::ChartThemeIcy:
52 53 return new ChartThemeIcy();
53 54 case QChart::ChartThemeGrayscale:
54 55 return new ChartThemeGrayscale();
55 56 case QChart::ChartThemeScientific:
56 57 return new ChartThemeScientific();
57 58 default:
58 59 return new ChartThemeDefault();
59 60 }
60 61 }
61 62
62 63 void ChartTheme::decorate(QChart* chart)
63 64 {
64 65 chart->setChartBackgroundBrush(m_backgroundGradient);
65 66 }
66 67
68 void ChartTheme::decorate(QLegend* legend)
69 {
70 legend->setBackgroundBrush(m_backgroundGradient);
71 }
72
67 73 void ChartTheme::decorate(AreaChartItem* item, QAreaSeries* series, int index)
68 74 {
69 75 QPen pen;
70 76 QBrush brush;
71 77
72 78 if (pen != series->pen()){
73 79 item->setPen(series->pen());
74 80 } else {
75 81 pen.setColor(colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 1.0));
76 82 pen.setWidthF(2);
77 83 item->setPen(pen);
78 84 }
79 85
80 86 if (brush != series->brush()) {
81 87 item->setBrush(series->brush());
82 88 } else {
83 89 QBrush brush(m_seriesColors.at(index % m_seriesColors.size()));
84 90 item->setBrush(brush);
85 91 }
86 92 }
87 93
88 94
89 95 void ChartTheme::decorate(LineChartItem* item, QLineSeries* series,int index)
90 96 {
91 97 QPen pen;
92 98 if(pen != series->pen()){
93 99 item->setLinePen(series->pen());
94 100 return;
95 101 }
96 102 pen.setColor(m_seriesColors.at(index%m_seriesColors.size()));
97 103 pen.setWidthF(2);
98 104 item->setLinePen(pen);
99 105 }
100 106
101 107 void ChartTheme::decorate(BarPresenter* item, QBarSeries* series,int index)
102 108 {
103 109 QList<QBarSet*> sets = series->barSets();
104 110 for (int i=0; i<sets.count(); i++) {
105 111 qreal pos = 0.5;
106 112 if (sets.count() > 1)
107 113 pos = (qreal) i / (qreal) (sets.count() - 1);
108 114 QColor c = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), pos);
109 115 sets.at(i)->setBrush(QBrush(c));
110 116
111 117 // Pick label color as far as possible from bar color (within gradient).
112 118 // 0.3 is magic number that was picked as value that gave enough contrast with icy theme gradient :)
113 119 // TODO: better picking of label color?
114 120 if (pos < 0.3) {
115 121 c = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 1);
116 122 } else {
117 123 c = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 0);
118 124 }
119 125 sets.at(i)->setFloatingValuePen(QPen(c));
120 126 }
121 127 }
122 128
123 129 void ChartTheme::decorate(StackedBarPresenter* item, QStackedBarSeries* series,int index)
124 130 {
125 131 QList<QBarSet*> sets = series->barSets();
126 132 for (int i=0; i<sets.count(); i++) {
127 133 qreal pos = 0.5;
128 134 if (sets.count() > 1)
129 135 pos = (qreal) i / (qreal) (sets.count() - 1);
130 136 QColor c = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), pos);
131 137 sets.at(i)->setBrush(QBrush(c));
132 138
133 139 if (pos < 0.3) {
134 140 c = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 1);
135 141 } else {
136 142 c = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 0);
137 143 }
138 144 sets.at(i)->setFloatingValuePen(QPen(c));
139 145 }
140 146 }
141 147
142 148 void ChartTheme::decorate(PercentBarPresenter* item, QPercentBarSeries* series,int index)
143 149 {
144 150 QList<QBarSet*> sets = series->barSets();
145 151 for (int i=0; i<sets.count(); i++) {
146 152 qreal pos = 0.5;
147 153 if (sets.count() > 1)
148 154 pos = (qreal) i / (qreal) (sets.count() - 1);
149 155 QColor c = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), pos);
150 156 sets.at(i)->setBrush(QBrush(c));
151 157
152 158 if (pos < 0.3) {
153 159 c = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 1);
154 160 } else {
155 161 c = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 0);
156 162 }
157 163 sets.at(i)->setFloatingValuePen(QPen(c));
158 164 }
159 165 }
160 166
161 167 void ChartTheme::decorate(ScatterChartItem* item, QScatterSeries* series, int index)
162 168 {
163 169 Q_ASSERT(item);
164 170 Q_ASSERT(series);
165 171
166 172 // Use a base color for brush
167 173 item->setBrush(m_seriesColors.at(index % m_seriesColors.size()));
168 174
169 175 // Take pen near from gradient start, effectively using a lighter color for outline
170 176 QPen pen(QBrush(Qt::SolidPattern), 3);
171 177 pen.setColor(colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 1.0));
172 178 item->setPen(pen);
173 179 }
174 180
175 181 void ChartTheme::decorate(PiePresenter* item, QPieSeries* series, int index)
176 182 {
177 183 // Get color for a slice from a gradient linearly, beginning from the start of the gradient
178 184 for (int i(0); i < series->slices().count(); i++) {
179 185 qreal pos = (qreal) i / (qreal) series->count();
180 186 QColor penColor = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 0.1);
181 187 series->slices().at(i)->setSlicePen(penColor);
182 188 QColor brushColor = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), pos);
183 189 series->slices().at(i)->setSliceBrush(brushColor);
184 190 }
185 191 }
186 192
187 193
188 194 void ChartTheme::decorate(QChartAxis* axis, AxisItem* item)
189 195 {
190 196 //TODO: dummy defults for now
191 197 axis->setLabelsBrush(Qt::black);
192 198 axis->setLabelsPen(Qt::NoPen);
193 199 axis->setShadesPen(Qt::NoPen);
194 200 axis->setShadesOpacity(0.5);
195 201 }
196 202
197 203 void ChartTheme::decorate(SplineChartItem* item, QSplineSeries* series, int index)
198 204 {
199 205 Q_ASSERT(item);
200 206 Q_ASSERT(series);
201 207
202 208 QPen pen;
203 209
204 210 if(pen != series->pen()){
205 211 item->setLinePen(series->pen());
206 212 }else{
207 213 pen.setColor(m_seriesColors.at(index%m_seriesColors.size()));
208 214 pen.setWidthF(series->pen().widthF());
209 215 item->setLinePen(series->pen());
210 216 }
211 217
212 218 // QColor color = m_seriesColors.at(index % m_seriesColors.size());
213 219 // TODO: define alpha in the theme? or in the series?
214 220 //color.setAlpha(120);
215 221
216 222 // QBrush brush(color, Qt::SolidPattern);
217 223 // presenter->m_markerBrush = brush;
218 224
219 225 // QPen pen(brush, 3);
220 226 // pen.setColor(color);
221 227 // presenter->m_markerPen = pen;
222 228 }
223 229
224 230 void ChartTheme::generateSeriesGradients()
225 231 {
226 232 // Generate gradients in HSV color space
227 233 foreach (QColor color, m_seriesColors) {
228 234 QLinearGradient g;
229 235 qreal h = color.hsvHueF();
230 236 qreal s = color.hsvSaturationF();
231 237
232 238 // TODO: tune the algorithm to give nice results with most base colors defined in
233 239 // most themes. The rest of the gradients we can define manually in theme specific
234 240 // implementation.
235 241 QColor start = color;
236 242 start.setHsvF(h, 0.05, 0.95);
237 243 g.setColorAt(0.0, start);
238 244
239 245 g.setColorAt(0.5, color);
240 246
241 247 QColor end = color;
242 248 end.setHsvF(h, s, 0.25);
243 249 g.setColorAt(1.0, end);
244 250
245 251 m_seriesGradients << g;
246 252 }
247 253 }
248 254
249 255
250 256 QColor ChartTheme::colorAt(const QColor &start, const QColor &end, qreal pos)
251 257 {
252 258 Q_ASSERT(pos >=0.0 && pos <= 1.0);
253 259 qreal r = start.redF() + ((end.redF() - start.redF()) * pos);
254 260 qreal g = start.greenF() + ((end.greenF() - start.greenF()) * pos);
255 261 qreal b = start.blueF() + ((end.blueF() - start.blueF()) * pos);
256 262 QColor c;
257 263 c.setRgbF(r, g, b);
258 264 return c;
259 265 }
260 266
261 267 QColor ChartTheme::colorAt(const QGradient &gradient, qreal pos)
262 268 {
263 269 Q_ASSERT(pos >=0 && pos <= 1.0);
264 270
265 271 // another possibility:
266 272 // http://stackoverflow.com/questions/3306786/get-intermediate-color-from-a-gradient
267 273
268 274 QGradientStops stops = gradient.stops();
269 275 int count = stops.count();
270 276
271 277 // find previous stop relative to position
272 278 QGradientStop prev = stops.first();
273 279 for (int i=0; i<count; i++) {
274 280 QGradientStop stop = stops.at(i);
275 281 if (pos > stop.first)
276 282 prev = stop;
277 283
278 284 // given position is actually a stop position?
279 285 if (pos == stop.first) {
280 286 //qDebug() << "stop color" << pos;
281 287 return stop.second;
282 288 }
283 289 }
284 290
285 291 // find next stop relative to position
286 292 QGradientStop next = stops.last();
287 293 for (int i=count-1; i>=0; i--) {
288 294 QGradientStop stop = stops.at(i);
289 295 if (pos < stop.first)
290 296 next = stop;
291 297 }
292 298
293 299 //qDebug() << "prev" << prev.first << "pos" << pos << "next" << next.first;
294 300
295 301 qreal range = next.first - prev.first;
296 302 qreal posDelta = pos - prev.first;
297 303 qreal relativePos = posDelta / range;
298 304
299 305 //qDebug() << "range" << range << "posDelta" << posDelta << "relativePos" << relativePos;
300 306
301 307 return colorAt(prev.second, next.second, relativePos);
302 308 }
303 309
304 310 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,71 +1,72
1 1 #ifndef CHARTTHEME_H
2 2 #define CHARTTHEME_H
3 3
4 4 #include "qchartglobal.h"
5 5 #include "qchart.h"
6 6 #include <QColor>
7 7 #include <QGradientStops>
8 8
9 9 QTCOMMERCIALCHART_BEGIN_NAMESPACE
10 10
11 11 class ChartItem;
12 12 class QSeries;
13 13 class LineChartItem;
14 14 class QLineSeries;
15 15 class BarPresenter;
16 16 class QBarSeries;
17 17 class StackedBarPresenter;
18 18 class QStackedBarSeries;
19 19 class QPercentBarSeries;
20 20 class PercentBarPresenter;
21 21 class QScatterSeries;
22 22 class ScatterChartItem;
23 23 class PiePresenter;
24 24 class QPieSeries;
25 25 class SplineChartItem;
26 26 class QSplineSeries;
27 27 class AreaChartItem;
28 28 class QAreaSeries;
29 29
30 30 class ChartTheme
31 31 {
32 32 protected:
33 33 explicit ChartTheme(QChart::ChartTheme id = QChart::ChartThemeDefault);
34 34 public:
35 35 static ChartTheme* createTheme(QChart::ChartTheme theme);
36 36 QChart::ChartTheme id() const {return m_id;}
37 37 void decorate(QChart* chart);
38 void decorate(QLegend* legend);
38 39 //void decorate(ChartItem* item, QSeries* series,int index);
39 40 void decorate(BarPresenter* item, QBarSeries* series, int index);
40 41 void decorate(StackedBarPresenter* item, QStackedBarSeries* series, int index);
41 42 void decorate(PercentBarPresenter* item, QPercentBarSeries* series, int index);
42 43 void decorate(LineChartItem* item, QLineSeries* series, int index);
43 44 void decorate(AreaChartItem* item, QAreaSeries* series, int index);
44 45 void decorate(ScatterChartItem* presenter, QScatterSeries* series, int index);
45 46 void decorate(PiePresenter* item, QPieSeries* series, int index);
46 47 void decorate(QChartAxis* axis,AxisItem* item);
47 48 void decorate(SplineChartItem* presenter, QSplineSeries* series, int index);
48 49
49 50 public: // utils
50 51 void generateSeriesGradients();
51 52 static QColor colorAt(const QColor &start, const QColor &end, qreal pos);
52 53 static QColor colorAt(const QGradient &gradient, qreal pos);
53 54
54 55 protected:
55 56 QChart::ChartTheme m_id;
56 57 QList<QColor> m_seriesColors;
57 58 QList<QGradient> m_seriesGradients;
58 59 QLinearGradient m_backgroundGradient;
59 60
60 61 // TODO: Add something like the following to themes:
61 62 // QPen axisLinePen;
62 63 // QPen backgroundHorizontalGridPen;
63 64 // QPen backgroundVerticalGridPen;
64 65 // // FillAll, FillEverySecondRow, FillEverySecondColumn, FillEverySecondRowAndColumn, FillNone
65 66 // int backgroundType;
66 67 // QFont masterFont;
67 68 };
68 69
69 70 QTCOMMERCIALCHART_END_NAMESPACE
70 71
71 72 #endif // CHARTTHEME_H
@@ -1,334 +1,344
1 1 #include "qchart.h"
2 2 #include "qchartaxis.h"
3 3 #include "qlegend.h"
4 4 #include "chartpresenter_p.h"
5 5 #include "chartdataset_p.h"
6 6 #include <QGraphicsScene>
7 7 #include <QGraphicsSceneResizeEvent>
8 8 #include <QDebug>
9 9
10 10 QTCOMMERCIALCHART_BEGIN_NAMESPACE
11 11
12 12 /*!
13 13 \enum QChart::ChartTheme
14 14
15 15 This enum describes the theme used by the chart.
16 16
17 17 \value ChartThemeDefault
18 18 \value ChartThemeVanilla
19 19 \value ChartThemeIcy
20 20 \value ChartThemeGrayscale
21 21 \value ChartThemeScientific
22 22 */
23 23
24 24 /*!
25 25 \enum QChart::AnimationOption
26 26
27 27 For enabling/disabling animations. Defaults to NoAnimation.
28 28
29 29 \value NoAnimation
30 30 \value GridAxisAnimations
31 31 \value SeriesAnimations
32 32 \value AllAnimations
33 33 */
34 34
35 35 /*!
36 36 \class QChart
37 37 \brief QtCommercial chart API.
38 38
39 39 QChart is a QGraphicsWidget that you can show in a QGraphicsScene. It manages the graphical
40 40 representation of different types of QChartSeries and other chart related objects like
41 41 QChartAxis and QChartLegend. If you simply want to show a chart in a layout, you can use the
42 42 convenience class QChartView instead of QChart.
43 43 \sa QChartView
44 44 */
45 45
46 46 /*!
47 47 Constructs a chart object which is a child of a\a parent. Parameter \a wFlags is passed to the QGraphicsWidget constructor.
48 48 */
49 49 QChart::QChart(QGraphicsItem *parent, Qt::WindowFlags wFlags) : QGraphicsWidget(parent,wFlags),
50 50 m_backgroundItem(0),
51 51 m_titleItem(0),
52 52 m_dataset(new ChartDataSet(this)),
53 m_presenter(new ChartPresenter(this,m_dataset)),
54 m_legend(new QLegend(this)) // TODO: is this the parent we want the legend to have?
53 m_presenter(new ChartPresenter(this,m_dataset))
55 54 {
55 createLegend();
56 56 connect(m_dataset,SIGNAL(seriesAdded(QSeries*,Domain*)),m_legend,SLOT(handleSeriesAdded(QSeries*,Domain*)));
57 57 connect(m_dataset,SIGNAL(seriesRemoved(QSeries*)),m_legend,SLOT(handleSeriesRemoved(QSeries*)));
58 58 }
59 59
60 60 /*!
61 61 Destroys the object and it's children, like QChartSeries and QChartAxis object added to it.
62 62 */
63 63 QChart::~QChart()
64 64 {
65 65 disconnect(m_dataset,SIGNAL(seriesAdded(QSeries*,Domain*)),m_legend,SLOT(handleSeriesAdded(QSeries*,Domain*)));
66 66 disconnect(m_dataset,SIGNAL(seriesRemoved(QSeries*)),m_legend,SLOT(handleSeriesRemoved(QSeries*)));
67 67 }
68 68
69 69 /*!
70 70 Adds the \a series and optional \a axisY onto the chart and takes the ownership of the objects.
71 71 If auto scaling is enabled, re-scales the axes the series is bound to (both the x axis and
72 72 the y axis).
73 73 */
74 74 void QChart::addSeries(QSeries* series, QChartAxis* axisY)
75 75 {
76 76 m_dataset->addSeries(series, axisY);
77 77 }
78 78
79 79 /*!
80 80 Removes the \a series specified in a perameter from the QChartView.
81 81 It releses its ownership of the specified QChartSeries object.
82 82 It does not delete the pointed QChartSeries data object
83 83 \sa addSeries(), removeAllSeries()
84 84 */
85 85 void QChart::removeSeries(QSeries* series)
86 86 {
87 87 m_dataset->removeSeries(series);
88 88 }
89 89
90 90 /*!
91 91 Removes all the QChartSeries that have been added to the QChartView
92 92 It also deletes the pointed QChartSeries data objects
93 93 \sa addSeries(), removeSeries()
94 94 */
95 95 void QChart::removeAllSeries()
96 96 {
97 97 m_dataset->removeAllSeries();
98 98 }
99 99
100 100 /*!
101 101 Sets the \a brush that is used for painting the background of the chart area.
102 102 */
103 103 void QChart::setChartBackgroundBrush(const QBrush& brush)
104 104 {
105 105 createChartBackgroundItem();
106 106 m_backgroundItem->setBrush(brush);
107 107 m_backgroundItem->update();
108 108 }
109 109
110 110 /*!
111 111 Sets the \a pen that is used for painting the background of the chart area.
112 112 */
113 113 void QChart::setChartBackgroundPen(const QPen& pen)
114 114 {
115 115 createChartBackgroundItem();
116 116 m_backgroundItem->setPen(pen);
117 117 m_backgroundItem->update();
118 118 }
119 119
120 120 /*!
121 121 Sets the chart \a title. The description text that is drawn above the chart.
122 122 */
123 123 void QChart::setChartTitle(const QString& title)
124 124 {
125 125 createChartTitleItem();
126 126 m_titleItem->setText(title);
127 127 }
128 128
129 129 /*!
130 130 Returns the chart title. The description text that is drawn above the chart.
131 131 */
132 132 QString QChart::chartTitle() const
133 133 {
134 134 if(m_titleItem)
135 135 return m_titleItem->text();
136 136 else
137 137 return QString();
138 138 }
139 139
140 140 /*!
141 141 Sets the \a font that is used for rendering the description text that is rendered above the chart.
142 142 */
143 143 void QChart::setChartTitleFont(const QFont& font)
144 144 {
145 145 createChartTitleItem();
146 146 m_titleItem->setFont(font);
147 147 }
148 148
149 149 /*!
150 150 Sets the \a brush used for rendering the title text.
151 151 */
152 152 void QChart::setChartTitleBrush(const QBrush &brush)
153 153 {
154 154 createChartTitleItem();
155 155 m_titleItem->setBrush(brush);
156 156 }
157 157
158 158 /*!
159 159 Returns the brush used for rendering the title text.
160 160 */
161 161 QBrush QChart::chartTitleBrush()
162 162 {
163 163 createChartTitleItem();
164 164 return m_titleItem->brush();
165 165 }
166 166
167 167 void QChart::createChartBackgroundItem()
168 168 {
169 169 if(!m_backgroundItem) {
170 170 m_backgroundItem = new QGraphicsRectItem(this);
171 171 m_backgroundItem->setPen(Qt::NoPen);
172 172 m_backgroundItem->setZValue(ChartPresenter::BackgroundZValue);
173 173 }
174 174 }
175 175
176 176 void QChart::createChartTitleItem()
177 177 {
178 178 if(!m_titleItem) {
179 179 m_titleItem = new QGraphicsSimpleTextItem(this);
180 180 m_titleItem->setZValue(ChartPresenter::BackgroundZValue);
181 181 }
182 182 }
183 183
184 void QChart::createLegend()
185 {
186 // TODO: Why we have null pointer, even if this is created in constructor?
187 if(!m_legend) {
188 m_legend = new QLegend(this);
189 m_legend->setZValue(ChartPresenter::LegendZValue);
190 }
191 }
192
193
184 194 /*!
185 195 Returns the chart margin, which is the distance between the widget edge and the part of the chart where the actual data can be displayed.
186 196 \sa setMargin()
187 197 */
188 198 int QChart::margin() const
189 199 {
190 200 return m_presenter->margin();
191 201 }
192 202
193 203 /*!
194 204 Sets the chart \a margin, which is the distance between the widget edge and the part of the chart where the actual data can be displayed.
195 205 \sa margin()
196 206 */
197 207 void QChart::setMargin(int margin)
198 208 {
199 209 m_presenter->setMargin(margin);
200 210 }
201 211
202 212 /*!
203 213 Sets the \a theme used by the chart for rendering the graphical representation of the data
204 214 \sa ChartTheme, chartTheme()
205 215 */
206 216 void QChart::setChartTheme(QChart::ChartTheme theme)
207 217 {
208 218 m_presenter->setChartTheme(theme);
209 219 }
210 220
211 221 /*!
212 222 Returns the theme enum used by the chart.
213 223 \sa ChartTheme, setChartTheme()
214 224 */
215 225 QChart::ChartTheme QChart::chartTheme() const
216 226 {
217 227 return m_presenter->chartTheme();
218 228 }
219 229
220 230 /*!
221 231 Zooms in the view by a factor of 2
222 232 */
223 233 void QChart::zoomIn()
224 234 {
225 235 m_presenter->zoomIn();
226 236 }
227 237
228 238 /*!
229 239 Zooms in the view to a maximum level at which \a rect is still fully visible.
230 240 */
231 241 void QChart::zoomIn(const QRectF& rect)
232 242 {
233 243
234 244 if(!rect.isValid()) return;
235 245 m_presenter->zoomIn(rect);
236 246 }
237 247
238 248 /*!
239 249 Restores the view zoom level to the previous one.
240 250 */
241 251 void QChart::zoomOut()
242 252 {
243 253 m_presenter->zoomOut();
244 254 }
245 255
246 256 /*!
247 257 Resets to the default view.
248 258 */
249 259 void QChart::zoomReset()
250 260 {
251 261 m_presenter->zoomReset();
252 262 }
253 263
254 264 /*!
255 265 Returns the pointer to the x axis object of the chart
256 266 */
257 267 QChartAxis* QChart::axisX() const
258 268 {
259 269 return m_dataset->axisX();
260 270 }
261 271
262 272 /*!
263 273 Returns the pointer to the y axis object of the chart
264 274 */
265 275 QChartAxis* QChart::axisY() const
266 276 {
267 277 return m_dataset->axisY();
268 278 }
269 279
270 280 /*!
271 281 Returns the legend object of the chart
272 282 */
273 QLegend* QChart::legend() const
283 QLegend* QChart::legend()
274 284 {
285 createLegend();
275 286 return m_legend;
276 287 }
277 288
278
279 289 /*!
280 290 Resizes and updates the chart area using the \a event data
281 291 */
282 292 void QChart::resizeEvent(QGraphicsSceneResizeEvent *event)
283 293 {
284 294
285 295 m_rect = QRectF(QPoint(0,0),event->newSize());
286 296 QRectF rect = m_rect.adjusted(margin(),margin(), -margin(), -margin());
287 297
288 298 // recalculate title position
289 299 if (m_titleItem) {
290 300 QPointF center = m_rect.center() -m_titleItem->boundingRect().center();
291 301 m_titleItem->setPos(center.x(),m_rect.top()/2 + margin()/2);
292 302 }
293 303
294 304 //recalculate background gradient
295 305 if (m_backgroundItem) {
296 306 m_backgroundItem->setRect(rect);
297 307 }
298 308
299 309 QGraphicsWidget::resizeEvent(event);
300 310 update();
301 311 }
302 312
303 313 /*!
304 314 Sets animation \a options for the chart
305 315 */
306 316 void QChart::setAnimationOptions(AnimationOptions options)
307 317 {
308 318 m_presenter->setAnimationOptions(options);
309 319 }
310 320
311 321 /*!
312 322 Returns animation options for the chart
313 323 */
314 324 QChart::AnimationOptions QChart::animationOptions() const
315 325 {
316 326 return m_presenter->animationOptions();
317 327 }
318 328
319 329 void QChart::scroll(int dx,int dy)
320 330 {
321 331 //temporary
322 332 if(dx>0)
323 333 m_presenter->scroll(m_presenter->geometry().width()/(axisX()->ticksCount()-1),0);
324 334 if(dx<0)
325 335 m_presenter->scroll(-m_presenter->geometry().width()/(axisX()->ticksCount()-1),0);
326 336 if(dy>0)
327 337 m_presenter->scroll(0,m_presenter->geometry().width()/(axisY()->ticksCount()-1));
328 338 if(dy<0)
329 339 m_presenter->scroll(0,-m_presenter->geometry().width()/(axisY()->ticksCount()-1));
330 340 }
331 341
332 342 #include "moc_qchart.cpp"
333 343
334 344 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,103 +1,104
1 1 #ifndef QCHART_H
2 2 #define QCHART_H
3 3
4 4 #include <qchartglobal.h>
5 5 #include <qseries.h>
6 6 #include <QGraphicsWidget>
7 7 #include <QLinearGradient>
8 8 #include <QFont>
9 9
10 10 class QGraphicsSceneResizeEvent;
11 11
12 12 QTCOMMERCIALCHART_BEGIN_NAMESPACE
13 13
14 14 class AxisItem;
15 15 class QSeries;
16 16 class PlotDomain;
17 17 class BarPresenter;
18 18 class QChartAxis;
19 19 class ChartTheme;
20 20 class ChartItem;
21 21 class ChartDataSet;
22 22 class ChartPresenter;
23 23 class QLegend;
24 24
25 25 class QTCOMMERCIALCHART_EXPORT QChart : public QGraphicsWidget
26 26 {
27 27 Q_OBJECT
28 28 public:
29 29 enum ChartTheme {
30 30 ChartThemeDefault,
31 31 ChartThemeVanilla,
32 32 ChartThemeIcy,
33 33 ChartThemeGrayscale,
34 34 ChartThemeScientific
35 35 //ChartThemeUnnamed1
36 36 /*! The default theme follows the GUI style of the Operating System */
37 37 };
38 38
39 39 enum AnimationOption {
40 40 NoAnimation = 0x0,
41 41 GridAxisAnimations = 0x1,
42 42 SeriesAnimations =0x2,
43 43 AllAnimations = 0x3
44 44 };
45 45 Q_DECLARE_FLAGS(AnimationOptions, AnimationOption)
46 46
47 47 public:
48 48 QChart(QGraphicsItem *parent = 0, Qt::WindowFlags wFlags = 0);
49 49 ~QChart();
50 50
51 51 void addSeries(QSeries* series, QChartAxis* axisY = 0);
52 52 void removeSeries(QSeries* series); //returns ownership , deletes axis if no series attached
53 53 void removeAllSeries(); // deletes series and axis
54 54
55 55 void setMargin(int margin);
56 56 int margin() const;
57 57 void setChartTheme(QChart::ChartTheme theme);
58 58 QChart::ChartTheme chartTheme() const;
59 59
60 60 void setChartTitle(const QString& title);
61 61 QString chartTitle() const;
62 62 void setChartTitleFont(const QFont& font);
63 63 void setChartTitleBrush(const QBrush &brush);
64 64 QBrush chartTitleBrush();
65 65 void setChartBackgroundBrush(const QBrush& brush);
66 66 void setChartBackgroundPen(const QPen& pen);
67 67
68 68 void setAnimationOptions(AnimationOptions options);
69 69 AnimationOptions animationOptions() const;
70 70
71 71 void zoomIn();
72 72 void zoomIn(const QRectF& rect);
73 73 void zoomOut();
74 74 void zoomReset();
75 75 void scroll(int dx,int dy);
76 76
77 77 QChartAxis* axisX() const;
78 78 QChartAxis* axisY() const;
79 79
80 QLegend* legend() const;
80 QLegend* legend();
81 81
82 82 protected:
83 83 void resizeEvent(QGraphicsSceneResizeEvent *event);
84 84
85 85 private:
86 86 inline void createChartBackgroundItem();
87 87 inline void createChartTitleItem();
88 inline void createLegend();
88 89
89 90 private:
90 91 Q_DISABLE_COPY(QChart)
91 92 QGraphicsRectItem* m_backgroundItem;
92 93 QGraphicsSimpleTextItem* m_titleItem;
93 94 QRectF m_rect;
94 95 ChartDataSet *m_dataset;
95 96 ChartPresenter *m_presenter;
96 97 QLegend* m_legend;
97 98 };
98 99
99 100 QTCOMMERCIALCHART_END_NAMESPACE
100 101
101 102 Q_DECLARE_OPERATORS_FOR_FLAGS(QTCOMMERCIALCHART_NAMESPACE::QChart::AnimationOptions)
102 103
103 104 #endif
@@ -1,389 +1,388
1 1 #include "qchartview.h"
2 2 #include "qchart.h"
3 3 #include "qchartaxis.h"
4 4 #include <QGraphicsView>
5 5 #include <QGraphicsScene>
6 6 #include <QRubberBand>
7 7 #include <QResizeEvent>
8 8 #include <QDebug>
9 9
10 10 /*!
11 11 \enum QChartView::RubberBandPolicy
12 12
13 13 This enum describes the different types of rubber bands that can be used for zoom rect selection
14 14
15 15 \value NoRubberBand
16 16 \value VerticalRubberBand
17 17 \value HorizonalRubberBand
18 18 \value RectangleRubberBand
19 19 */
20 20
21 21 /*!
22 22 \class QChartView
23 23 \brief Standalone charting widget.
24 24
25 25 QChartView is a standalone widget that can display charts. It does not require separate
26 26 QGraphicsScene to work. It manages the graphical representation of different types of
27 27 QChartSeries and other chart related objects like QChartAxis and QChartLegend. If you want to
28 28 display a chart in your existing QGraphicsScene, you can use the QChart class instead.
29 29
30 30 \sa QChart
31 31 */
32 32
33 33 QTCOMMERCIALCHART_BEGIN_NAMESPACE
34 34
35 35 /*!
36 36 Constructs a chartView object which is a child of a\a parent.
37 37 */
38 38 QChartView::QChartView(QWidget *parent) :
39 39 QGraphicsView(parent),
40 40 m_scene(new QGraphicsScene(this)),
41 41 m_chart(new QChart()),
42 42 m_rubberBand(0),
43 43 m_verticalRubberBand(false),
44 44 m_horizonalRubberBand(false)
45 45 {
46 46 setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
47 47 setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
48 48 setScene(m_scene);
49 49 m_chart->setMargin(50);
50 50 m_scene->addItem(m_chart);
51 51 setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
52 52 }
53 53
54 54
55 55 /*!
56 56 Destroys the object and it's children, like QChartSeries and QChartAxis object added to it.
57 57 */
58 58 QChartView::~QChartView()
59 59 {
60 60 }
61 61
62 62 /*!
63 63 Resizes and updates the chart area using the \a event data
64 64 */
65 65 void QChartView::resizeEvent(QResizeEvent *event)
66 66 {
67 67 m_scene->setSceneRect(0,0,size().width(),size().height());
68 68 m_chart->resize(size());
69 69 QWidget::resizeEvent(event);
70 70 }
71 71
72 72 /*!
73 73 Adds the \a series and optional \a axisY onto the chart and takes the ownership of the objects.
74 74 If auto scaling is enabled, re-scales the axes the series is bound to (both the x axis and
75 75 the y axis).
76 76 \sa removeSeries(), removeAllSeries()
77 77 */
78 78 void QChartView::addSeries(QSeries* series,QChartAxis *axisY)
79 79 {
80 80 m_chart->addSeries(series,axisY);
81 81 }
82 82
83 83 /*!
84 84 Removes the \a series specified in a perameter from the QChartView.
85 85 It releses its ownership of the specified QChartSeries object.
86 86 It does not delete the pointed QChartSeries data object
87 87 \sa addSeries(), removeAllSeries()
88 88 */
89 89 void QChartView::removeSeries(QSeries* series)
90 90 {
91 91 m_chart->removeSeries(series);
92 92 }
93 93
94 94 /*!
95 95 Removes all the QChartSeries that have been added to the QChartView
96 96 It also deletes the pointed QChartSeries data objects
97 97 \sa addSeries(), removeSeries()
98 98 */
99 99 void QChartView::removeAllSeries()
100 100 {
101 101 m_chart->removeAllSeries();
102 102 }
103 103
104 104 /*!
105 105 Zooms in the view by a factor of 2
106 106 */
107 107 void QChartView::zoomIn()
108 108 {
109 109 m_chart->zoomIn();
110 110 }
111 111
112 112 /*!
113 113 Zooms in the view to a maximum level at which \a rect is still fully visible.
114 114 */
115 115 void QChartView::zoomIn(const QRect& rect)
116 116 {
117 117 m_chart->zoomIn(rect);
118 118 }
119 119
120 120 /*!
121 121 Restores the view zoom level to the previous one.
122 122 */
123 123 void QChartView::zoomOut()
124 124 {
125 125 m_chart->zoomOut();
126 126 }
127 127
128 128 /*!
129 129 Returns the chart margin, which is the distance between the widget edge and the part of the chart where the actual data can be displayed.
130 130 */
131 131 int QChartView::margin() const
132 132 {
133 133 return m_chart->margin();
134 134 }
135 135
136 136 /*!
137 137 Sets the chart \a title. A description text that is drawn above the chart.
138 138 */
139 139 void QChartView::setChartTitle(const QString& title)
140 140 {
141 141 m_chart->setChartTitle(title);
142 142 }
143 143
144 144 /*!
145 145 Returns the chart's title. A description text that is drawn above the chart.
146 146 */
147 147 QString QChartView::chartTitle() const
148 148 {
149 149 return m_chart->chartTitle();
150 150 }
151 151
152 152 /*!
153 153 Sets the \a font that is used for rendering the description text that is rendered above the chart.
154 154 */
155 155 void QChartView::setChartTitleFont(const QFont& font)
156 156 {
157 157 m_chart->setChartTitleFont(font);
158 158 }
159 159
160 160 /*!
161 161 Sets the \a brush used for rendering the title text.
162 162 */
163 163 void QChartView::setChartTitleBrush(const QBrush &brush)
164 164 {
165 165 m_chart->setChartTitleBrush(brush);
166 166 }
167 167
168 168 /*!
169 169 Returns the brush used for rendering the title text.
170 170 */
171 171 QBrush QChartView::chartTitleBrush()
172 172 {
173 173 return m_chart->chartTitleBrush();
174 174 }
175 175
176 176 /*!
177 177 Sets the \a brush that is used for painting the background of the chart area of the QChartView widget.
178 178 */
179 179 void QChartView::setChartBackgroundBrush(const QBrush& brush)
180 180 {
181 181 m_chart->setChartBackgroundBrush(brush);
182 182 }
183 183
184 184 /*!
185 185 Sets the \a pen that is used for painting the background of the chart area of the QChartView widget.
186 186 */
187 187 void QChartView::setChartBackgroundPen(const QPen& pen)
188 188 {
189 189 m_chart->setChartBackgroundPen(pen);
190 190 }
191 191
192 192 /*!
193 193 Sets the RubberBandPlicy to \a policy. Selected policy determines the way zooming is performed.
194 194 */
195 195 void QChartView::setRubberBandPolicy(const RubberBandPolicy policy)
196 196 {
197 197 switch(policy) {
198 198 case VerticalRubberBand:
199 199 m_verticalRubberBand = true;
200 200 m_horizonalRubberBand = false;
201 201 break;
202 202 case HorizonalRubberBand:
203 203 m_verticalRubberBand = false;
204 204 m_horizonalRubberBand = true;
205 205 break;
206 206 case RectangleRubberBand:
207 207 m_verticalRubberBand = true;
208 208 m_horizonalRubberBand = true;
209 209 break;
210 210 case NoRubberBand:
211 211 default:
212 212 delete m_rubberBand;
213 213 m_rubberBand=0;
214 214 m_horizonalRubberBand = false;
215 215 m_verticalRubberBand = false;
216 216 return;
217 217 }
218 218 if(!m_rubberBand) {
219 219 m_rubberBand = new QRubberBand(QRubberBand::Rectangle, this);
220 220 m_rubberBand->setEnabled(true);
221 221 }
222 222 }
223 223
224 224 /*!
225 225 Returns the RubberBandPolicy that is currently being used by the widget.
226 226 */
227 227 QChartView::RubberBandPolicy QChartView::rubberBandPolicy() const
228 228 {
229 229 if(m_horizonalRubberBand && m_verticalRubberBand) return RectangleRubberBand;
230 230 if(m_horizonalRubberBand) return HorizonalRubberBand;
231 231 if(m_verticalRubberBand) return VerticalRubberBand;
232 232 return NoRubberBand;
233 233 }
234 234
235 235 /*!
236 236 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.
237 237 If different mouse button is pressed and/or the RubberBandPolicy is disabled then the \a event is passed to QGraphicsView::mousePressEvent() implementation.
238 238 */
239 239 void QChartView::mousePressEvent(QMouseEvent *event)
240 240 {
241 241 if(m_rubberBand && m_rubberBand->isEnabled() && event->button() == Qt::LeftButton) {
242 242
243 243 int margin = m_chart->margin();
244 244 QRect rect(margin, margin, width() - 2 * margin, height() - 2 * margin);
245 245
246 246 if (rect.contains(event->pos())) {
247 247 m_rubberBandOrigin = event->pos();
248 248 m_rubberBand->setGeometry(QRect(m_rubberBandOrigin, QSize()));
249 249 m_rubberBand->show();
250 250 event->accept();
251 251 }
252 252 }
253 253 else {
254 254 QGraphicsView::mousePressEvent(event);
255 255 }
256 256 }
257 257
258 258 /*!
259 259 If RubberBand rectange specification has been initiated in pressEvent then \a event data is used to update RubberBand geometry.
260 260 In other case the defualt QGraphicsView::mouseMoveEvent implementation is called.
261 261 */
262 262 void QChartView::mouseMoveEvent(QMouseEvent *event)
263 263 {
264 264 if(m_rubberBand && m_rubberBand->isVisible()) {
265 265 int margin = m_chart->margin();
266 266 QRect rect(margin, margin, width() - 2 * margin, height() - 2 * margin);
267 267 int width = event->pos().x() - m_rubberBandOrigin.x();
268 268 int height = event->pos().y() - m_rubberBandOrigin.y();
269 269 if(!m_verticalRubberBand) {
270 270 m_rubberBandOrigin.setY(rect.top());
271 271 height = rect.height();
272 272 }
273 273 if(!m_horizonalRubberBand) {
274 274 m_rubberBandOrigin.setX(rect.left());
275 275 width= rect.width();
276 276 }
277 277 m_rubberBand->setGeometry(QRect(m_rubberBandOrigin.x(),m_rubberBandOrigin.y(), width,height).normalized());
278 278 }
279 279 else {
280 280 QGraphicsView::mouseMoveEvent(event);
281 281 }
282 282 }
283 283
284 284 /*!
285 285 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
286 286 If it is the right mouse button \a event then RubberBand is dissmissed and zoom is canceled.
287 287 */
288 288 void QChartView::mouseReleaseEvent(QMouseEvent *event)
289 289 {
290 290 if(m_rubberBand) {
291 291 if (event->button() == Qt::LeftButton && m_rubberBand->isVisible()) {
292 292 m_rubberBand->hide();
293 293 QRect rect = m_rubberBand->geometry();
294 294 m_chart->zoomIn(rect);
295 295 event->accept();
296 296 }
297 297
298 298 if(event->button()==Qt::RightButton)
299 299 m_chart->zoomReset();
300 300 }
301 301 else {
302 302 QGraphicsView::mouseReleaseEvent(event);
303 303 }
304 304 }
305 305
306 306 /*!
307 307 Pressing + and - keys performs zoomIn() and zoomOut() respectivly.
308 308 In other \a event is passed to the QGraphicsView::keyPressEvent() implementation
309 309 */
310 310 void QChartView::keyPressEvent(QKeyEvent *event)
311 311 {
312 312 switch (event->key()) {
313 313 case Qt::Key_Plus:
314 314 zoomIn();
315 315 break;
316 316 case Qt::Key_Minus:
317 317 zoomOut();
318 318 break;
319 319 default:
320 320 QGraphicsView::keyPressEvent(event);
321 321 break;
322 322 }
323 323 }
324 324
325 325 /*!
326 326 Sets the \a theme used by the chart for rendering the graphical representation of the data
327 327 \sa QChart::ChartTheme, chartTheme()
328 328 */
329 329 void QChartView::setChartTheme(QChart::ChartTheme theme)
330 330 {
331 331 m_chart->setChartTheme(theme);
332 332 }
333 333
334 334 /*!
335 335 Returns the theme enum used by the chart.
336 336 \sa setChartTheme()
337 337 */
338 338 QChart::ChartTheme QChartView::chartTheme() const
339 339 {
340 340 return m_chart->chartTheme();
341 341 }
342 342
343 343 /*!
344 344 Returns the pointer to the x axis object of the chart
345 345 */
346 346 QChartAxis* QChartView::axisX() const
347 347 {
348 348 return m_chart->axisX();
349 349 }
350 350
351 351 /*!
352 352 Returns the pointer to the y axis object of the chart
353 353 */
354 354 QChartAxis* QChartView::axisY() const
355 355 {
356 356 return m_chart->axisY();
357 357 }
358 358
359 359 /*!
360 360 Returns the pointer to legend object of the chart
361 361 */
362 362 QLegend* QChartView::legend() const
363 363 {
364 364 return m_chart->legend();
365 365 }
366 366
367
368 367 /*!
369 368 Sets animation \a options for the chart
370 369 */
371 370 void QChartView::setAnimationOptions(QChart::AnimationOptions options)
372 371 {
373 372 m_chart->setAnimationOptions(options);
374 373 }
375 374
376 375 /*!
377 376 Returns animation options for the chart
378 377 */
379 378 QChart::AnimationOptions QChartView::animationOptions() const
380 379 {
381 380 return m_chart->animationOptions();
382 381 }
383 382
384 383 void QChartView::scroll(int dx,int dy)
385 384 {
386 385 m_chart->scroll(dx,dy);
387 386 }
388 387
389 388 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,127 +1,140
1 1 #include "qchartglobal.h"
2 2 #include "qlegend.h"
3 3 #include "qseries.h"
4 4 #include <QPainter>
5 5 #include <QPen>
6 6
7 7 QTCOMMERCIALCHART_BEGIN_NAMESPACE
8 8
9 9 // TODO: this to legendmarker_p.h header
10 10 class LegendMarker : public QGraphicsItem
11 11 {
12 12 public:
13 13 LegendMarker(QGraphicsItem *parent = 0) : QGraphicsItem(parent)
14 14 ,mBoundingRect(0,0,1,1)
15 15 {}
16 16
17 17 void setBoundingRect(const QRectF rect) { mBoundingRect = rect; }
18 18 void setBrush(const QBrush brush) { mBrush = brush; }
19 19 void setName(const QString name) { mName = name; }
20 20 QString name() const { return mName; }
21 21 QColor color() const { return mBrush.color(); }
22 22
23 23 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0)
24 24 {
25 qDebug() << "LegendMarker::paint" << mBoundingRect;
26 25 painter->setBrush(mBrush);
27 26 painter->drawRect(mBoundingRect);
28 27 }
29 28
30 29 QRectF boundingRect() const { return mBoundingRect; }
31 30
32 31 private:
33 32 QRectF mBoundingRect;
34 33 QBrush mBrush;
35 34 QString mName;
36 35 };
37 36
38 37 QLegend::QLegend(QGraphicsItem *parent)
39 38 : QGraphicsObject(parent)
40 39 ,mBoundingRect(0,0,1,1)
40 ,mBackgroundBrush(Qt::darkGray) // TODO: from theme?
41 41 {
42 42 }
43 43
44 44 void QLegend::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
45 45 {
46 // TODO: layout for text. using marker layout + magic for now.
46 painter->setBrush(mBackgroundBrush);
47 painter->drawRect(mBoundingRect);
48
47 49 foreach(LegendMarker* m, mMarkers) {
48 50 QRectF r = m->boundingRect();
49 51 painter->setPen(m->color());
50 // TODO: r.y + r.height is incorrect. should be r.y. Find the bug, and remove the hack
51 painter->drawText(r.x() + 20, r.y()+r.height(), m->name());
52 painter->drawText(r.x() + 20, r.y() + r.height(), m->name());
52 53 }
53 54 }
54 55
55 56 QRectF QLegend::boundingRect() const
56 57 {
57 58 return mBoundingRect;
58 59 }
59 60
61 void QLegend::setBackgroundBrush(const QBrush& brush)
62 {
63 mBackgroundBrush = brush;
64 }
65
66 QBrush QLegend::backgroundBrush() const
67 {
68 return mBackgroundBrush;
69 }
70
60 71 void QLegend::handleSeriesAdded(QSeries* series,Domain* domain)
61 72 {
62 73 mSeriesList.append(series);
63 74 dataChanged();
64 75 layoutChanged();
65 76 }
66 77
67 78 void QLegend::handleSeriesRemoved(QSeries* series)
68 79 {
69 80 mSeriesList.removeOne(series);
70 81 dataChanged();
71 82 layoutChanged();
72 83 }
73 84
74 85 void QLegend::handleGeometryChanged(const QRectF& size)
75 86 {
76 87 mBoundingRect = size;
77 88 layoutChanged();
78 89 }
79 90
80 91 void QLegend::dataChanged()
81 92 {
82 93 foreach (QGraphicsItem* i, childItems()) {
83 94 delete i;
84 95 }
85 96
86 97 mMarkers.clear();
87 98
88 99 foreach (QSeries* s, mSeriesList) {
89 100 for (int i=0; i<s->legendEntries().count(); i++) {
90 101 LegendMarker *marker = new LegendMarker(this);
91 102 marker->setBrush(s->legendEntries().at(i).mBrush);
92 103 marker->setName(s->legendEntries().at(i).mName);
93 104 mMarkers.append(marker);
94 childItems().append(marker);
105 // childItems().append(marker);
95 106 }
96 107 }
97 108 }
98 109
99
100 110 void QLegend::layoutChanged()
101 111 {
102 112 // Calculate layout for markers and text
103 113 if (mMarkers.count() <= 0) {
104 114 // Nothing to do
105 115 return;
106 116 }
107 117
108 118 // TODO: marker defined by series.
109 119 QSizeF markerSize(10,10);
110 120
111 121 // TODO: better layout, this is just concept.
112 122 // Leave some space around markers like this: | x x x x |
113 qreal steps = mMarkers.count() * 2 + 1;
123 qreal steps = mMarkers.count();
114 124
125 qreal xStep = mBoundingRect.width() / steps;
115 126 qreal yStep = mBoundingRect.height() / steps;
116 qreal x = 0;
117 qreal y = yStep; // first step is empty
127 qreal x = mBoundingRect.x() + 5;
128 qreal y = mBoundingRect.y() + (mBoundingRect.height() - markerSize.height())/2;
118 129 foreach (LegendMarker* m, mMarkers) {
130 qDebug() << "marker x:" << x;
131 qDebug() << "marker y:" << y;
119 132 m->setBoundingRect(QRectF(x,y,markerSize.width(),markerSize.height()));
120 y += yStep*2; // 2 steps per marker (marker and empty space)
133 x += xStep;
121 134 }
122 135 }
123 136
124 137
125 138
126 139 #include "moc_qlegend.cpp"
127 140 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,41 +1,46
1 1 #ifndef QLEGEND_H
2 2 #define QLEGEND_H
3 3
4 4 #include "qchartglobal.h"
5 5 #include "qseries.h"
6 6 #include <QGraphicsObject>
7 7
8 8 QTCOMMERCIALCHART_BEGIN_NAMESPACE
9 9
10 10 class Domain;
11 11 class LegendMarker;
12 12
13 13 class QTCOMMERCIALCHART_EXPORT QLegend : public QGraphicsObject
14 14 {
15 15 Q_OBJECT
16 16 public:
17 17
18 18 explicit QLegend(QGraphicsItem *parent = 0);
19 19
20 20 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
21 21 QRectF boundingRect() const;
22 22
23 void setBackgroundBrush(const QBrush& brush);
24 QBrush backgroundBrush() const;
25
23 26 signals:
24 27
25 28 public slots:
26 29 void handleSeriesAdded(QSeries* series,Domain* domain);
27 30 void handleSeriesRemoved(QSeries* series);
28 31 void handleGeometryChanged(const QRectF& size);
29 32
30 33 private:
31 34 void dataChanged();
32 35 void layoutChanged();
33 36
34 37 QRectF mBoundingRect;
35 38 QList<QSeries*> mSeriesList;
36 39 QList<LegendMarker*> mMarkers;
40
41 QBrush mBackgroundBrush;
37 42 };
38 43
39 44 QTCOMMERCIALCHART_END_NAMESPACE
40 45
41 46 #endif // QLEGEND_H
General Comments 0
You need to be logged in to leave comments. Login now