##// END OF EJS Templates
Refactored chartwidgettest test data impl
Tero Ahola -
r278:1d8f8b316dca
parent child
Show More
@@ -1,49 +1,51
1 1 #include <QtGui/QApplication>
2 2 #include <QMainWindow>
3 3 #include <qchartglobal.h>
4 4 #include <qchartview.h>
5 5 #include <qscatterseries.h>
6 6
7 7 QTCOMMERCIALCHART_USE_NAMESPACE
8 8
9 9 int main(int argc, char *argv[])
10 10 {
11 11 QApplication a(argc, argv);
12 12
13 13 // Create chart widget
14 14 QChartView *chartView = new QChartView();
15 15
16 //! [1]
16 17 // Add scatter series with simple test data
17 18 QScatterSeries *scatter = new QScatterSeries();
18 19 *scatter << QPointF(0.5, 5.0)
19 20 << QPointF(1.0, 4.5)
20 21 << QPointF(1.0, 5.5)
21 22 << QPointF(1.5, 5.0)
22 23 << QPointF(2.0, 4.5)
23 24 << QPointF(2.0, 5.5)
24 25 << QPointF(2.5, 5.0);
25 26 // Chart takes ownership
26 27 chartView->addSeries(scatter);
28 //! [1]
27 29
28 30 // Add another scatter series
29 31 // - more data with random component
30 32 QScatterSeries *scatter2 = new QScatterSeries();
31 33 for (qreal i(0.0); i < 20; i += 0.15) {
32 34 (*scatter2) << QPointF(i + (qreal)(rand() % 100) / 100.0,
33 35 i + (qreal)(rand() % 100) / 100.0);
34 36 }
35 37 QBrush brush(QColor(255, 0, 0, 100), Qt::SolidPattern);
36 38 scatter2->setMarkerBrush(brush);
37 39 QPen pen(QColor(0, 255, 0, 80), 3);
38 40 scatter2->setMarkerPen(pen);
39 41 scatter2->setMarkerShape(QScatterSeries::MarkerShapeRectangle);
40 42 chartView->addSeries(scatter2);
41 43
42 44 // Use the chart widget as the central widget
43 45 QMainWindow w;
44 46 w.resize(640, 480);
45 47 w.setCentralWidget(chartView);
46 48 w.show();
47 49
48 50 return a.exec();
49 51 }
@@ -1,229 +1,229
1 1 #include "charttheme_p.h"
2 2 #include "qchart.h"
3 3 #include "qchartaxis.h"
4 4
5 5
6 6 //series
7 7 #include "qbarset.h"
8 8 #include "qbarchartseries.h"
9 9 #include "qstackedbarchartseries.h"
10 10 #include "qpercentbarchartseries.h"
11 11 #include "qlinechartseries.h"
12 12 #include "qscatterseries.h"
13 13 #include "qpieseries.h"
14 14 #include "qpieslice.h"
15 15
16 16 //items
17 17 #include "axisitem_p.h"
18 18 #include "barpresenter.h"
19 19 #include "stackedbarpresenter.h"
20 20 #include "linechartitem_p.h"
21 21 #include "percentbarpresenter.h"
22 22 #include "scatterpresenter_p.h"
23 23 #include "piepresenter.h"
24 24
25 25 //themes
26 26 #include "chartthemevanilla_p.h"
27 27 #include "chartthemeicy_p.h"
28 28 #include "chartthemegrayscale_p.h"
29 29 #include "chartthemescientific_p.h"
30 30
31 31
32 32 QTCOMMERCIALCHART_BEGIN_NAMESPACE
33 33
34 34 /* TODO
35 35 case QChart::ChartThemeUnnamed1:
36 36 m_seriesThemes.append(SeriesTheme(QColor(QRgb(0xff3fa9f5)), 2));
37 37 m_seriesThemes.append(SeriesTheme(QColor(QRgb(0xff7AC943)), 2));
38 38 m_seriesThemes.append(SeriesTheme(QColor(QRgb(0xffFF931E)), 2));
39 39 m_seriesThemes.append(SeriesTheme(QColor(QRgb(0xffFF1D25)), 2));
40 40 m_seriesThemes.append(SeriesTheme(QColor(QRgb(0xffFF7BAC)), 2));
41 41
42 42 m_gradientStartColor = QColor(QRgb(0xfff3dc9e));
43 43 m_gradientEndColor = QColor(QRgb(0xffafafaf));
44 44 */
45 45
46 46 ChartTheme::ChartTheme(QChart::ChartTheme id)
47 47 {
48 48 m_id = id;
49 49 m_seriesColor.append(QRgb(0xff000000));
50 50 m_seriesColor.append(QRgb(0xff707070));
51 51 m_gradientStartColor = QColor(QRgb(0xffffffff));
52 52 m_gradientEndColor = QColor(QRgb(0xffafafaf));
53 53 }
54 54
55 55
56 56 ChartTheme* ChartTheme::createTheme(QChart::ChartTheme theme)
57 57 {
58 58 switch(theme) {
59 59 case QChart::ChartThemeDefault:
60 60 return new ChartTheme();
61 61 case QChart::ChartThemeVanilla:
62 62 return new ChartThemeVanilla();
63 63 case QChart::ChartThemeIcy:
64 64 return new ChartThemeIcy();
65 65 case QChart::ChartThemeGrayscale:
66 66 return new ChartThemeGrayscale();
67 67 case QChart::ChartThemeScientific:
68 68 return new ChartThemeScientific();
69 69 }
70 70 }
71 71
72 72 void ChartTheme::decorate(QChart* chart)
73 73 {
74 74 QLinearGradient backgroundGradient;
75 75 backgroundGradient.setColorAt(0.0, m_gradientStartColor);
76 76 backgroundGradient.setColorAt(1.0, m_gradientEndColor);
77 77 backgroundGradient.setCoordinateMode(QGradient::ObjectBoundingMode);
78 78 chart->setChartBackgroundBrush(backgroundGradient);
79 79 }
80 80 //TODO helper to by removed later
81 81 void ChartTheme::decorate(ChartItem* item, QChartSeries* series,int count)
82 82 {
83 83 switch(series->type())
84 84 {
85 85 case QChartSeries::SeriesTypeLine: {
86 86 QLineChartSeries* s = static_cast<QLineChartSeries*>(series);
87 87 LineChartItem* i = static_cast<LineChartItem*>(item);
88 88 decorate(i,s,count);
89 89 break;
90 90 }
91 91 case QChartSeries::SeriesTypeBar: {
92 92 QBarChartSeries* b = static_cast<QBarChartSeries*>(series);
93 93 BarPresenter* i = static_cast<BarPresenter*>(item);
94 94 decorate(i,b,count);
95 95 break;
96 96 }
97 97 case QChartSeries::SeriesTypeStackedBar: {
98 98 QStackedBarChartSeries* s = static_cast<QStackedBarChartSeries*>(series);
99 99 StackedBarPresenter* i = static_cast<StackedBarPresenter*>(item);
100 100 decorate(i,s,count);
101 101 break;
102 102 }
103 103 case QChartSeries::SeriesTypePercentBar: {
104 104 QPercentBarChartSeries* s = static_cast<QPercentBarChartSeries*>(series);
105 105 PercentBarPresenter* i = static_cast<PercentBarPresenter*>(item);
106 106 decorate(i,s,count);
107 107 break;
108 108 }
109 109 case QChartSeries::SeriesTypeScatter: {
110 110 QScatterSeries* s = qobject_cast<QScatterSeries*>(series);
111 111 Q_ASSERT(s);
112 112 ScatterPresenter* i = static_cast<ScatterPresenter*>(item);
113 113 Q_ASSERT(i);
114 114 decorate(i, s, count);
115 115 break;
116 116 }
117 117 case QChartSeries::SeriesTypePie: {
118 118 QPieSeries* s = static_cast<QPieSeries*>(series);
119 119 PiePresenter* i = static_cast<PiePresenter*>(item);
120 120 decorate(i,s,count);
121 121 break;
122 122 }
123 123 default:
124 124 qDebug()<<"Wrong item to be decorated by theme";
125 125 break;
126 126 }
127 127
128 128 }
129 129
130 130 void ChartTheme::decorate(LineChartItem* item, QLineChartSeries* series,int count)
131 131 {
132 132 QPen pen;
133 133 if(pen != series->pen()){
134 134 item->setPen(series->pen());
135 135 return;
136 136 }
137 137 pen.setColor(m_seriesColor.at(count%m_seriesColor.size()));
138 138 pen.setWidthF(2);
139 139 item->setPen(pen);
140 140 }
141 141
142 142 void ChartTheme::decorate(BarPresenter* item, QBarChartSeries* series,int count)
143 143 {
144 144 for (int i=0; i<series->countSets(); i++) {
145 145 series->nextSet(0==i)->setBrush(QBrush(m_seriesColor.at(i%m_seriesColor.count())));
146 146 }
147 147 }
148 148
149 149 void ChartTheme::decorate(StackedBarPresenter* item, QStackedBarChartSeries* series,int count)
150 150 {
151 151 for (int i=0; i<series->countSets(); i++) {
152 152 series->nextSet(0==i)->setBrush(QBrush(m_seriesColor.at(i%m_seriesColor.count())));
153 153 }
154 154 }
155 155
156 156 void ChartTheme::decorate(PercentBarPresenter* item, QPercentBarChartSeries* series,int count)
157 157 {
158 158 for (int i=0; i<series->countSets(); i++) {
159 159 series->nextSet(0==i)->setBrush(QBrush(m_seriesColor.at(i%m_seriesColor.count())));
160 160 }
161 161 }
162 162
163 163 void ChartTheme::decorate(ScatterPresenter* presenter, QScatterSeries* series, int count)
164 164 {
165 165 Q_ASSERT(presenter);
166 166 Q_ASSERT(series);
167 167
168 168 QColor color = m_seriesColor.at(count % m_seriesColor.size());
169 169 // TODO: define alpha in the theme? or in the series?
170 color.setAlpha(120);
170 //color.setAlpha(120);
171 171
172 172 QBrush brush(color, Qt::SolidPattern);
173 173 presenter->m_markerBrush = brush;
174 174
175 QPen pen(brush, 1);
175 QPen pen(brush, 3);
176 176 pen.setColor(color);
177 177 presenter->m_markerPen = pen;
178 178 }
179 179
180 180 void ChartTheme::decorate(PiePresenter* item, QPieSeries* series, int /*count*/)
181 181 {
182 182 // create a list of slice colors based on current theme
183 183 int i = 0;
184 184 QList<QColor> colors;
185 185 while (colors.count() < series->count()) {
186 186
187 187 // get base color
188 188 QColor c = m_seriesColor[i++];
189 189 i = i % m_seriesColor.count();
190 190
191 191 // -1 means achromatic color -> cannot manipulate lightness
192 192 // TODO: find a better way to randomize lightness
193 193 if (c.toHsv().hue() == -1)
194 194 qWarning() << "ChartTheme::decorate() warning: achromatic theme color";
195 195
196 196 // randomize lightness
197 197 qreal f = 50 + (qrand() % 100); // 50 is 50% darker, 100 is the same, 150 is 50% lighter
198 198 c = c.lighter(f);
199 199
200 200 // find duplicates
201 201 bool isUnique = true;
202 202 foreach (QColor color, colors) {
203 203 if (c == color)
204 204 isUnique = false;
205 205 }
206 206
207 207 // add to array if unique
208 208 //if (isUnique)
209 209 colors << c;
210 210 }
211 211
212 212 // finally update colors
213 213 foreach (QPieSlice* s, series->slices()) {
214 214 s->setPen(QPen(Qt::black)); // TODO: get from theme
215 215 s->setBrush(colors.takeFirst());
216 216 }
217 217 }
218 218
219 219
220 220 void ChartTheme::decorate(QChartAxis* axis,AxisItem* item)
221 221 {
222 222 //TODO: dummy defults for now
223 223 axis->setLabelsBrush(Qt::black);
224 224 axis->setLabelsPen(Qt::NoPen);
225 225 axis->setShadesPen(Qt::NoPen);
226 226 axis->setShadesOpacity(0.5);
227 227 }
228 228
229 229 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,299 +1,299
1 1 #include "qpieseries.h"
2 2 #include "qpieslice.h"
3 3 #include "piepresenter.h"
4 4 #include "pieslice.h"
5 5 #include <QDebug>
6 6
7 7 QTCOMMERCIALCHART_BEGIN_NAMESPACE
8 8
9 9 void QPieSeries::ChangeSet::appendAdded(QPieSlice* slice)
10 10 {
11 11 if (!m_added.contains(slice))
12 12 m_added << slice;
13 13 }
14 14
15 15 void QPieSeries::ChangeSet::appendChanged(QPieSlice* slice)
16 16 {
17 17 if (!m_changed.contains(slice))
18 18 m_changed << slice;
19 19 }
20 20
21 21 void QPieSeries::ChangeSet::appendRemoved(QPieSlice* slice)
22 22 {
23 23 if (!m_removed.contains(slice))
24 24 m_removed << slice;
25 25 }
26 26
27 27 QList<QPieSlice*> QPieSeries::ChangeSet::added() const
28 28 {
29 29 return m_added;
30 30 }
31 31
32 32 QList<QPieSlice*> QPieSeries::ChangeSet::changed() const
33 33 {
34 34 return m_changed;
35 35 }
36 36
37 37 QList<QPieSlice*> QPieSeries::ChangeSet::removed() const
38 38 {
39 39 return m_removed;
40 40 }
41 41
42 42 bool QPieSeries::ChangeSet::isEmpty() const
43 43 {
44 44 if (m_added.count() || m_changed.count() || m_removed.count())
45 45 return false;
46 46 return true;
47 47 }
48 48
49 49
50 50 QPieSeries::QPieSeries(QObject *parent) :
51 51 QChartSeries(parent),
52 52 m_sizeFactor(1.0),
53 53 m_position(PiePositionMaximized),
54 54 m_pieStartAngle(0),
55 55 m_pieSpan(360)
56 56 {
57 57
58 58 }
59 59
60 60 QPieSeries::~QPieSeries()
61 61 {
62 62
63 63 }
64 64
65 65 bool QPieSeries::setData(QList<qreal> data)
66 66 {
67 67 // TODO: remove this function
68 68 QList<QPieSlice*> slices;
69 foreach (int value, data)
69 foreach (qreal value, data)
70 70 slices << new QPieSlice(value, QString::number(value));
71 71 set(slices);
72 72 return true;
73 73 }
74 74
75 75 void QPieSeries::set(QList<QPieSlice*> slices)
76 76 {
77 77 clear();
78 78 add(slices);
79 79 }
80 80
81 81 void QPieSeries::add(QList<QPieSlice*> slices)
82 82 {
83 83 ChangeSet changeSet;
84 84 foreach (QPieSlice* s, slices) {
85 85 s->setParent(this);
86 86 m_slices << s;
87 87 changeSet.appendAdded(s);
88 88 }
89 89
90 90 updateDerivativeData();
91 91
92 92 foreach (QPieSlice* s, slices) {
93 93 connect(s, SIGNAL(changed()), this, SLOT(sliceChanged()));
94 94 connect(s, SIGNAL(clicked()), this, SLOT(sliceClicked()));
95 95 connect(s, SIGNAL(hoverEnter()), this, SLOT(sliceHoverEnter()));
96 96 connect(s, SIGNAL(hoverLeave()), this, SLOT(sliceHoverLeave()));
97 97 }
98 98
99 99 emit changed(changeSet);
100 100 }
101 101
102 102 void QPieSeries::add(QPieSlice* slice)
103 103 {
104 104 add(QList<QPieSlice*>() << slice);
105 105 }
106 106
107 107 QPieSlice* QPieSeries::add(qreal value, QString name)
108 108 {
109 109 QPieSlice* slice = new QPieSlice(value, name);
110 110 add(slice);
111 111 return slice;
112 112 }
113 113
114 114 void QPieSeries::remove(QPieSlice* slice)
115 115 {
116 116 if (!m_slices.removeOne(slice)) {
117 117 Q_ASSERT(0); // TODO: remove before release
118 118 return;
119 119 }
120 120
121 121 ChangeSet changeSet;
122 122 changeSet.appendRemoved(slice);
123 123 emit changed(changeSet);
124 124
125 125 delete slice;
126 126 slice = NULL;
127 127
128 128 updateDerivativeData();
129 129 }
130 130
131 131 void QPieSeries::clear()
132 132 {
133 133 if (m_slices.count() == 0)
134 134 return;
135 135
136 136 ChangeSet changeSet;
137 137 foreach (QPieSlice* s, m_slices) {
138 138 changeSet.appendRemoved(s);
139 139 m_slices.removeOne(s);
140 140 delete s;
141 141 }
142 142 emit changed(changeSet);
143 143 updateDerivativeData();
144 144 }
145 145
146 146 void QPieSeries::setSizeFactor(qreal factor)
147 147 {
148 148 if (factor < 0.0)
149 149 return;
150 150
151 151 if (m_sizeFactor != factor) {
152 152 m_sizeFactor = factor;
153 153 emit sizeFactorChanged();
154 154 }
155 155 }
156 156
157 157 void QPieSeries::setPosition(PiePosition position)
158 158 {
159 159 if (m_position != position) {
160 160 m_position = position;
161 161 emit positionChanged();
162 162 }
163 163 }
164 164
165 165 void QPieSeries::setSpan(qreal startAngle, qreal span)
166 166 {
167 167 if (startAngle >= 0 && startAngle < 360 &&
168 168 span > 0 && span <= 360) {
169 169 m_pieStartAngle = startAngle;
170 170 m_pieSpan = span;
171 171 updateDerivativeData();
172 172 }
173 173 }
174 174
175 175 void QPieSeries::setLabelsVisible(bool visible)
176 176 {
177 177 foreach (QPieSlice* s, m_slices)
178 178 s->setLabelVisible(visible);
179 179 }
180 180
181 181 void QPieSeries::enableClickExplodes(bool enable)
182 182 {
183 183 if (enable)
184 184 connect(this, SIGNAL(clicked(QPieSlice*)), this, SLOT(toggleExploded(QPieSlice*)));
185 185 else
186 186 disconnect(this, SLOT(toggleExploded(QPieSlice*)));
187 187 }
188 188
189 189 void QPieSeries::enableHoverHighlight(bool enable)
190 190 {
191 191 if (enable) {
192 192 connect(this, SIGNAL(hoverEnter(QPieSlice*)), this, SLOT(highlightOn(QPieSlice*)));
193 193 connect(this, SIGNAL(hoverLeave(QPieSlice*)), this, SLOT(highlightOff(QPieSlice*)));
194 194 } else {
195 195 disconnect(this, SLOT(hoverEnter(QPieSlice*)));
196 196 disconnect(this, SLOT(hoverLeave(QPieSlice*)));
197 197 }
198 198 }
199 199
200 200 void QPieSeries::sliceChanged()
201 201 {
202 202 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
203 203 Q_ASSERT(m_slices.contains(slice));
204 204
205 205 ChangeSet changeSet;
206 206 changeSet.appendChanged(slice);
207 207 emit changed(changeSet);
208 208
209 209 updateDerivativeData();
210 210 }
211 211
212 212 void QPieSeries::sliceClicked()
213 213 {
214 214 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
215 215 Q_ASSERT(m_slices.contains(slice));
216 216 emit clicked(slice);
217 217 }
218 218
219 219 void QPieSeries::sliceHoverEnter()
220 220 {
221 221 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
222 222 Q_ASSERT(m_slices.contains(slice));
223 223 emit hoverEnter(slice);
224 224 }
225 225
226 226 void QPieSeries::sliceHoverLeave()
227 227 {
228 228 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
229 229 Q_ASSERT(m_slices.contains(slice));
230 230 emit hoverLeave(slice);
231 231 }
232 232
233 233 void QPieSeries::toggleExploded(QPieSlice* slice)
234 234 {
235 235 Q_ASSERT(slice);
236 236 slice->setExploded(!slice->isExploded());
237 237 }
238 238
239 239 void QPieSeries::highlightOn(QPieSlice* slice)
240 240 {
241 241 Q_ASSERT(slice);
242 242 QColor c = slice->brush().color().lighter();
243 243 slice->setBrush(c);
244 244 }
245 245
246 246 void QPieSeries::highlightOff(QPieSlice* slice)
247 247 {
248 248 Q_ASSERT(slice);
249 249 QColor c = slice->brush().color().darker(150);
250 250 slice->setBrush(c);
251 251 }
252 252
253 253 void QPieSeries::updateDerivativeData()
254 254 {
255 255 m_total = 0;
256 256
257 257 // nothing to do?
258 258 if (m_slices.count() == 0)
259 259 return;
260 260
261 261 // calculate total
262 262 foreach (QPieSlice* s, m_slices)
263 263 m_total += s->value();
264 264
265 265 // we must have some values
266 266 Q_ASSERT(m_total > 0); // TODO
267 267
268 268 // update slice attributes
269 269 qreal sliceAngle = m_pieStartAngle;
270 270 foreach (QPieSlice* s, m_slices) {
271 271
272 272 bool changed = false;
273 273
274 274 qreal percentage = s->value() / m_total;
275 275 if (s->m_percentage != percentage) {
276 276 s->m_percentage = percentage;
277 277 changed = true;
278 278 }
279 279
280 280 qreal sliceSpan = m_pieSpan * percentage;
281 281 if (s->m_span != sliceSpan) {
282 282 s->m_span = sliceSpan;
283 283 changed = true;
284 284 }
285 285
286 286 if (s->m_angle != sliceAngle) {
287 287 s->m_angle = sliceAngle;
288 288 changed = true;
289 289 }
290 290 sliceAngle += sliceSpan;
291 291
292 292 if (changed)
293 293 emit s->changed();
294 294 }
295 295 }
296 296
297 297 #include "moc_qpieseries.cpp"
298 298
299 299 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,207 +1,208
1 1 #include "qscatterseries.h"
2 2 #include "scatterseries_p.h"
3 3 #include "qchart.h"
4 4
5 5 QTCOMMERCIALCHART_BEGIN_NAMESPACE
6 6
7 7 QScatterSeriesPrivate::QScatterSeriesPrivate() :
8 8 m_data(QList<QPointF>()),
9 9 m_markerPen(QPen()),
10 10 m_markerBrush(QBrush()),
11 11 m_markerShape(QScatterSeries::MarkerShapeDefault)
12 12 {
13 13 // Initialize pen color to invalid to use a theme color by default
14 14 m_markerPen.setColor(QColor::Invalid);
15 15 m_markerBrush.setColor(QColor::Invalid);
16 16 }
17 17
18 18 /*!
19 19 \enum QScatterSeries::MarkerShape
20 20
21 21 This enum describes the shape used when rendering marker items.
22 22
23 23 \value MarkerShapeDefault
24 24 \value MarkerShapePoint
25 25 \value MarkerShapeX
26 26 \value MarkerShapeRectangle
27 27 \value MarkerShapeTiltedRectangle
28 28 \value MarkerShapeTriangle
29 29 \value MarkerShapeCircle
30 30 */
31 31
32 32 /*!
33 33 \class QScatterSeries
34 34 \brief QtCommercial Chart series API for showing scatter series.
35 35
36 \snippet ../../example/scatter/main.cpp 1
36 37 Example on how to create a chart with scatter series:
37 38 \code
38 39 #include <qchartglobal.h>
39 40 #include <qchartview.h>
40 41 #include <qscatterseries.h>
41 42 ...
42 43 QTCOMMERCIALCHART_USE_NAMESPACE
43 44
44 45 // Create chart widget
45 46 QChartView *chartView = new QChartView();
46 47 QScatterSeries *scatter = new QScatterSeries();
47 48 *scatter << QPointF(0.5, 5.0) << QPointF(1.0, 4.5) << QPointF(1.0, 5.5) << QPointF(1.5, 5.0);
48 49 chartView->addSeries(scatter);
49 50 // Then add the QChartView into a layout...
50 51 \endcode
51 52
52 53 The example code would result the following:
53 54
54 55 \image scatter_example1.jpg
55 56 */
56 57
57 58 /*!
58 59 Constructs a series object which is a child of \a parent.
59 60 */
60 61 QScatterSeries::QScatterSeries(QObject *parent) :
61 62 QChartSeries(parent),
62 63 d(new QScatterSeriesPrivate())
63 64 {
64 65 }
65 66
66 67 /*!
67 68 Destroys the object. Note that adding series to QChart transfers the ownership to the chart.
68 69 */
69 70 QScatterSeries::~QScatterSeries()
70 71 {
71 72 delete d;
72 73 }
73 74
74 75 /*!
75 76 Add single data point to the series.
76 77 For example:
77 78 \code
78 79 mySeries.addData(QPointF(0.5, 5.0));
79 80 \endcode
80 81 */
81 82 void QScatterSeries::addData(QPointF value)
82 83 {
83 84 d->m_data.append(value);
84 85 emit changed();
85 86 }
86 87
87 88 /*!
88 89 Stream operator for adding a data point to the series.
89 90 \sa addData(), QScatterSeries::addData(QPointF value)
90 91
91 92 For example:
92 93 \code
93 94 mySeries << QPointF(0.5, 5.0)
94 95 << QPointF(1.0, 4.5);
95 96 \endcode
96 97
97 98 */
98 99 QScatterSeries& QScatterSeries::operator << (const QPointF &value)
99 100 {
100 101 d->m_data.append(value);
101 102 emit changed();
102 103 return *this;
103 104 }
104 105
105 106 /*!
106 107 Replaces the data of the series with the given list of data points.
107 108 */
108 109 void QScatterSeries::setData(QList<QPointF> data)
109 110 {
110 111 d->m_data = data;
111 112 emit changed();
112 113 }
113 114
114 115 /*!
115 116 Returns the current list of data points of the series.
116 117 */
117 118 QList<QPointF> QScatterSeries::data()
118 119 {
119 120 return d->m_data;
120 121 }
121 122
122 123 /*!
123 124 Overrides the default pen used for drawing a marker item with a user defined pen. The default
124 125 pen is defined by chart theme setting.
125 126
126 127 For example:
127 128 \code
128 129 QPen pen(QColor(0, 255, 0, 80), 3);
129 130 myScatter->setMarkerPen(pen);
130 131 \endcode
131 132
132 133 Would present your scatter markers with an opaque, uglyish green outlines:
133 134 \image scatter_example_pen.jpg
134 135
135 136 \sa setMarkerBrush()
136 137 \sa QChart::setTheme()
137 138 */
138 139 void QScatterSeries::setMarkerPen(QPen pen)
139 140 {
140 141 d->m_markerPen = pen;
141 142 }
142 143
143 144 /*!
144 145 Returns the pen used for drawing markers.
145 146 */
146 147 QPen QScatterSeries::markerPen()
147 148 {
148 149 return d->m_markerPen;
149 150 }
150 151
151 152 /*!
152 153 Overrides the default brush of the marker items with a user defined brush. The default
153 154 brush is defined by chart theme setting.
154 155
155 156 For example:
156 157 \code
157 158 QBrush brush(QColor(255, 0, 0, 100), Qt::SolidPattern);
158 159 myRandomScatter->setMarkerBrush(brush);
159 160 \endcode
160 161
161 162 Would fill your scatter markers with an opaque red color:
162 163 \image scatter_example_brush.jpg
163 164
164 165 \sa setMarkerPen()
165 166 \sa QChart::setTheme()
166 167 */
167 168 void QScatterSeries::setMarkerBrush(QBrush brush)
168 169 {
169 170 d->m_markerBrush = brush;
170 171 }
171 172
172 173 /*!
173 174 Returns the brush used for drawing markers.
174 175 */
175 176 QBrush QScatterSeries::markerBrush()
176 177 {
177 178 return d->m_markerBrush;
178 179 }
179 180
180 181 /*!
181 182 Overrides the default shape of the marker items with a user defined shape. The default
182 183 shape is defined by chart theme setting.
183 184
184 185 For example:
185 186 \code
186 187 myScatter->setMarkerShape(QScatterSeries::MarkerShapeRectangle);
187 188 \endcode
188 189
189 190 Would make your scatter marker items rectangle:
190 191 \image scatter_example_shape.jpg
191 192 */
192 193 void QScatterSeries::setMarkerShape(MarkerShape shape)
193 194 {
194 195 d->m_markerShape = shape;
195 196 }
196 197
197 198 /*!
198 199 Returns the shape used for drawing markers.
199 200 */
200 201 QScatterSeries::MarkerShape QScatterSeries::markerShape()
201 202 {
202 203 return (QScatterSeries::MarkerShape) d->m_markerShape;
203 204 }
204 205
205 206 #include "moc_qscatterseries.cpp"
206 207
207 208 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,113 +1,157
1 1 #include "scatterpresenter_p.h"
2 2 #include "qscatterseries.h"
3 3 #include <QPen>
4 4 #include <QPainter>
5 5 #include <QGraphicsScene>
6 6 #include <QDebug>
7 #include <QTime>
7 8
8 9 QTCOMMERCIALCHART_BEGIN_NAMESPACE
9 10
10 11 ScatterPresenter::ScatterPresenter(QScatterSeries *series, QGraphicsObject *parent) :
11 12 ChartItem(parent),
12 13 m_series(series),
13 14 m_boundingRect(),
14 15 //m_markerColor(QColor()),
15 16 // m_markerColor(QColor(255, 0, 0)),
16 17 m_visibleChartArea()
17 18 {
18 19 if (parent)
19 20 m_boundingRect = parent->boundingRect();
20 21
21 22 if (series) {
22 23 connect(series, SIGNAL(changed()), this, SLOT(handleModelChanged()));
23 24 }
24 25 }
25 26
26 27 void ScatterPresenter::handleDomainChanged(const Domain& domain)
27 28 {
28 29 m_visibleChartArea = domain;
29 30 changeGeometry();
30 31 }
31 32
32 33 void ScatterPresenter::handleGeometryChanged(const QRectF& rect)
33 34 {
34 35 m_boundingRect = rect;
35 36 changeGeometry();
36 37 }
37 38
38 39 void ScatterPresenter::handleModelChanged()
39 40 {
40 41 // TODO: more fine grained modelChanged signaling
41 42 changeGeometry();
42 43 }
43 44
44 45 void ScatterPresenter::paint(QPainter *painter, const QStyleOptionGraphicsItem */*option*/, QWidget */*widget*/)
45 46 {
46 47 // TODO: Optimization: avoid setting on every paint method call?
47 48 // The custom settings in series override those defined by the theme
48 if (m_series->markerPen().color().isValid())
49 painter->setPen(m_series->markerPen());
50 else
51 painter->setPen(m_markerPen);
49 int shape = m_series->markerShape();
50
51 painter->save();
52 painter->setClipRect(m_boundingRect);
53
54 // Paint dropshadow
55 QPen dropShadowPen(QColor(0, 0, 0, 70));
56 dropShadowPen.setWidth(3);
57 painter->setPen(dropShadowPen);
58 painter->setBrush(Qt::NoBrush);
59 painter->setRenderHint(QPainter::Antialiasing);
60 for (int i(0); i < m_scenex.count() && i < m_sceney.count(); i++) {
61 if (scene()->width() > m_scenex.at(i) && scene()->height() > m_sceney.at(i))
62 switch (shape) {
63 case QScatterSeries::MarkerShapeDefault:
64 // Fallthrough, defaults to circle
65 case QScatterSeries::MarkerShapeCircle:
66 painter->drawChord(m_scenex.at(i) + 2, m_sceney.at(i) + 2, 9, 9, 0, 5760);
67 break;
68 case QScatterSeries::MarkerShapePoint:
69 //painter->drawPoint(m_scenex.at(i), m_sceney.at(i));
70 break;
71 case QScatterSeries::MarkerShapeRectangle:
72 painter->drawRect(m_scenex.at(i) + 2, m_sceney.at(i) + 2, 8, 8);
73 break;
74 case QScatterSeries::MarkerShapeTiltedRectangle: {
75 // TODO:
76 static const QPointF points[4] = {
77 QPointF(-1.0 + m_scenex.at(i), 0.0 + m_sceney.at(i)),
78 QPointF(0.0 + m_scenex.at(i), 1.0 + m_sceney.at(i)),
79 QPointF(1.0 + m_scenex.at(i), 0.0 + m_sceney.at(i)),
80 QPointF(0.0 + m_scenex.at(i), -1.0 + m_sceney.at(i))
81 };
82 painter->drawPolygon(points, 4);
83 break;
84 }
85 default:
86 // TODO: implement the rest of the shapes
87 Q_ASSERT(false);
88 break;
89 }
90 }
52 91
92 // Paint the shape
93 QPen pen = m_markerPen;
94 if (m_series->markerPen().color().isValid())
95 pen = m_series->markerPen();
53 96 if (m_series->markerBrush().color().isValid())
54 97 painter->setBrush(m_series->markerBrush());
55 98 else
56 99 painter->setBrush(m_markerBrush);
57
58 int shape = m_series->markerShape();
59
100 painter->setPen(pen);
101 painter->setRenderHint(QPainter::Antialiasing, false);
60 102 for (int i(0); i < m_scenex.count() && i < m_sceney.count(); i++) {
61 103 if (scene()->width() > m_scenex.at(i) && scene()->height() > m_sceney.at(i))
62 // Paint a shape
63 104 switch (shape) {
64 105 case QScatterSeries::MarkerShapeDefault:
65 106 // Fallthrough, defaults to circle
66 107 case QScatterSeries::MarkerShapeCircle:
67 108 painter->drawChord(m_scenex.at(i), m_sceney.at(i), 9, 9, 0, 5760);
68 109 break;
69 110 case QScatterSeries::MarkerShapePoint:
70 111 painter->drawPoint(m_scenex.at(i), m_sceney.at(i));
71 112 break;
72 113 case QScatterSeries::MarkerShapeRectangle:
73 114 painter->drawRect(m_scenex.at(i), m_sceney.at(i), 9, 9);
74 115 break;
75 case QScatterSeries::MarkerShapeTiltedRectangle:
116 case QScatterSeries::MarkerShapeTiltedRectangle: {
76 117 // TODO:
77 118 static const QPointF points[4] = {
78 119 QPointF(-1.0 + m_scenex.at(i), 0.0 + m_sceney.at(i)),
79 120 QPointF(0.0 + m_scenex.at(i), 1.0 + m_sceney.at(i)),
80 121 QPointF(1.0 + m_scenex.at(i), 0.0 + m_sceney.at(i)),
81 122 QPointF(0.0 + m_scenex.at(i), -1.0 + m_sceney.at(i))
82 123 };
83 124 painter->drawPolygon(points, 4);
84 125 break;
126 }
85 127 default:
86 128 // TODO: implement the rest of the shapes
87 129 Q_ASSERT(false);
88 130 break;
89 131 }
90 132 }
133
134 painter->restore();
91 135 }
92 136
93 137 void ScatterPresenter::changeGeometry()
94 138 {
95 139 if (m_boundingRect.isValid()) {
96 140
97 141 prepareGeometryChange();
98 142 qreal scalex = m_boundingRect.width() / m_visibleChartArea.spanX();
99 143 qreal scaley = m_boundingRect.height() / m_visibleChartArea.spanY();
100 144 m_scenex.clear();
101 145 m_sceney.clear();
102 146
103 147 // Convert relative coordinates to absolute pixel coordinates that can be used for drawing
104 148 foreach (QPointF point, m_series->data()) {
105 149 m_scenex.append(m_boundingRect.left() + point.x() * scalex - m_visibleChartArea.m_minX * scalex);
106 150 m_sceney.append(m_boundingRect.bottom() - point.y() * scaley + m_visibleChartArea.m_minY * scaley);
107 151 }
108 152 }
109 153 }
110 154
111 155 #include "moc_scatterpresenter_p.cpp"
112 156
113 157 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,65 +1,149
1 1 #include "dataseriedialog.h"
2 2 #include <QDialogButtonBox>
3 3 #include <QGridLayout>
4 #include <QComboBox>
4 #include <QCheckbox>
5 5 #include <QPushButton>
6 #include <QGroupBox>
7 #include <QRadioButton>
6 8 #include <QLabel>
7 9 #include <QDebug>
8 10
9 11 DataSerieDialog::DataSerieDialog(QString defaultType, QWidget *parent) :
10 12 QDialog(parent)
11 13 {
12 // Combo box for selecting the series type
13 m_seriesTypeCombo = new QComboBox(this);
14 m_seriesTypeCombo->addItem("Line");
15 m_seriesTypeCombo->addItem("Area");
16 m_seriesTypeCombo->addItem("Bar");
17 m_seriesTypeCombo->addItem("StackedBar");
18 m_seriesTypeCombo->addItem("PercentBar");
19 m_seriesTypeCombo->addItem("Pie");
20 m_seriesTypeCombo->addItem("Scatter");
21 m_seriesTypeCombo->addItem("Spline");
22
23 // Allow pre-selection of a series type
24 if (defaultType != "") {
25 int index = m_seriesTypeCombo->findText(defaultType);
26 if (index > 0)
27 m_seriesTypeCombo->setCurrentIndex(index);
28 }
29
30 // Combo box for selecting data for the new series
31 m_testDataCombo = new QComboBox(this);
32 m_testDataCombo->addItem("linear");
33 m_testDataCombo->addItem("linear, 1M");
34 m_testDataCombo->addItem("SIN");
35 m_testDataCombo->addItem("SIN + random");
36 m_testDataCombo->addItem("Table, 5 series");
37 m_testDataCombo->addItem("TODO From file...");
38 m_testDataCombo->addItem("TODO From URL...");
39
40 14 QDialogButtonBox *addSeriesBox = new QDialogButtonBox(Qt::Horizontal);
41 15 QPushButton *b = addSeriesBox->addButton(QDialogButtonBox::Ok);
42 16 connect(b, SIGNAL(clicked()), this, SLOT(accept()));
43 17 b = addSeriesBox->addButton(QDialogButtonBox::Cancel);
44 18 connect(b, SIGNAL(clicked()), this, SLOT(reject()));
45 19
46 20 QGridLayout *grid = new QGridLayout();
47 grid->addWidget(new QLabel("Series type:"), 0, 0);
48 grid->addWidget(m_seriesTypeCombo, 0, 1);
49 grid->addWidget(new QLabel("Data:"), 1, 0);
50 grid->addWidget(m_testDataCombo, 1, 1);
51 grid->addWidget(addSeriesBox, 2, 1);
21
22 m_seriesTypeSelector = seriesTypeSelector();
23 m_columnCountSelector = columnCountSelector();
24 m_rowCountSelector = rowCountSelector();
25 m_dataCharacteristicsSelector = dataCharacteristicsSelector();
26
27 grid->addWidget(m_seriesTypeSelector, 0, 0);
28 grid->addWidget(m_columnCountSelector, 0, 1);
29 grid->addWidget(m_rowCountSelector, 1, 1);
30 grid->addWidget(m_dataCharacteristicsSelector, 1, 0);
31 m_labelsSelector = new QCheckBox("Labels defined");
32 m_labelsSelector->setChecked(true);
33 grid->addWidget(m_labelsSelector, 2, 0);
34 grid->addWidget(addSeriesBox, 3, 1);
52 35
53 36 setLayout(grid);
54 37 }
55 38
39 QGroupBox *DataSerieDialog::seriesTypeSelector()
40 {
41 QVBoxLayout *layout = new QVBoxLayout();
42
43 QRadioButton *line = new QRadioButton("&Line");
44 QRadioButton *area = new QRadioButton("&Area");
45 QRadioButton *pie = new QRadioButton("&Pie");
46 QRadioButton *bar = new QRadioButton("&Bar");
47 QRadioButton *scatter = new QRadioButton("&Scatter");
48 QRadioButton *spline = new QRadioButton("Spl&ine");
49 line->setChecked(true);
50
51 layout->addWidget(line);
52 layout->addWidget(area);
53 layout->addWidget(pie);
54 layout->addWidget(bar);
55 layout->addWidget(scatter);
56 layout->addWidget(spline);
57
58 QGroupBox *groupBox = new QGroupBox("Series type");
59 groupBox->setLayout(layout);
60
61 return groupBox;
62 }
63
64 QGroupBox *DataSerieDialog::columnCountSelector()
65 {
66 QVBoxLayout *layout = new QVBoxLayout();
67
68 QRadioButton *radio = new QRadioButton("1");
69 radio->setChecked(true);
70 layout->addWidget(radio);
71 layout->addWidget(new QRadioButton("2"));
72 layout->addWidget(new QRadioButton("3"));
73 layout->addWidget(new QRadioButton("5"));
74 layout->addWidget(new QRadioButton("10"));
75 layout->addWidget(new QRadioButton("100"));
76
77 QGroupBox *groupBox = new QGroupBox("Column count");
78 groupBox->setLayout(layout);
79
80 return groupBox;
81 }
82
83 QGroupBox *DataSerieDialog::rowCountSelector()
84 {
85 QVBoxLayout *layout = new QVBoxLayout();
86
87 layout->addWidget(new QRadioButton("1"));
88 QRadioButton *radio = new QRadioButton("10");
89 radio->setChecked(true);
90 layout->addWidget(radio);
91 layout->addWidget(new QRadioButton("50"));
92 layout->addWidget(new QRadioButton("100"));
93 layout->addWidget(new QRadioButton("10000"));
94 layout->addWidget(new QRadioButton("1000000"));
95
96 QGroupBox *groupBox = new QGroupBox("Row count");
97 groupBox->setLayout(layout);
98
99 return groupBox;
100 }
101
102 QGroupBox *DataSerieDialog::dataCharacteristicsSelector()
103 {
104 QVBoxLayout *layout = new QVBoxLayout();
105
106 QRadioButton *radio1 = new QRadioButton("Linear");
107 radio1->setChecked(true);
108 layout->addWidget(radio1);
109 layout->addWidget(new QRadioButton("Constant"));
110 layout->addWidget(new QRadioButton("Random"));
111 layout->addWidget(new QRadioButton("Sin"));
112 layout->addWidget(new QRadioButton("Sin + random"));
113
114 QGroupBox *groupBox = new QGroupBox("Data Characteristics");
115 groupBox->setLayout(layout);
116
117 return groupBox;
118 }
119
56 120 void DataSerieDialog::accept()
57 121 {
58 accepted(m_seriesTypeCombo->currentText(), m_testDataCombo->currentText());
122 accepted(radioSelection(m_seriesTypeSelector),
123 radioSelection(m_columnCountSelector).toInt(),
124 radioSelection(m_rowCountSelector).toInt(),
125 radioSelection(m_dataCharacteristicsSelector),
126 m_labelsSelector->isChecked());
59 127 QDialog::accept();
60 128 }
61 //void DataSerieDialog::addSeries(QAbstractButton *button)
62 //{
63 // addSeries(button->text().toAscii());
64 // accept();
65 //}
129
130 QString DataSerieDialog::radioSelection(QGroupBox *groupBox)
131 {
132 QString selection;
133 QVBoxLayout *layout = qobject_cast<QVBoxLayout *>(groupBox->layout());
134 Q_ASSERT(layout);
135
136 for (int i(0); i < layout->count(); i++) {
137 QLayoutItem *item = layout->itemAt(i);
138 Q_ASSERT(item);
139 QRadioButton *radio = qobject_cast<QRadioButton *>(item->widget());
140 Q_ASSERT(radio);
141 if (radio->isChecked()) {
142 selection = radio->text();
143 break;
144 }
145 }
146
147 qDebug() << "radioSelection: " << selection;
148 return selection;
149 }
@@ -1,25 +1,34
1 1 #ifndef DATASERIEDIALOG_H
2 2 #define DATASERIEDIALOG_H
3 3
4 4 #include <QDialog>
5 5
6 class QComboBox;
6 class QGroupBox;
7 class QCheckBox;
7 8
8 9 class DataSerieDialog : public QDialog
9 10 {
10 11 Q_OBJECT
11 12 public:
12 13 explicit DataSerieDialog(QString defaultType, QWidget *parent = 0);
13 14
14 15 signals:
15 void accepted(QString series, QString data);
16 void accepted(QString series, int columnCount, int rowCount, QString dataCharacteristics, bool labelsDefined);
16 17
17 18 public slots:
18 19 void accept();
19 20
20 21 private:
21 QComboBox *m_seriesTypeCombo;
22 QComboBox *m_testDataCombo;
22 QGroupBox *seriesTypeSelector();
23 QGroupBox *columnCountSelector();
24 QGroupBox *rowCountSelector();
25 QGroupBox *dataCharacteristicsSelector();
26 QString radioSelection(QGroupBox *groupBox);
27 QGroupBox *m_seriesTypeSelector;
28 QGroupBox *m_columnCountSelector;
29 QGroupBox *m_rowCountSelector;
30 QCheckBox *m_labelsSelector;
31 QGroupBox *m_dataCharacteristicsSelector;
23 32 };
24 33
25 34 #endif // DATASERIEDIALOG_H
@@ -1,431 +1,343
1 1 #include "mainwidget.h"
2 2 #include "dataseriedialog.h"
3 3 #include "qchartseries.h"
4 4 #include "qpieseries.h"
5 5 #include "qscatterseries.h"
6 6 #include <qlinechartseries.h>
7 7 #include <qbarset.h>
8 8 #include <qbarcategory.h>
9 9 #include <qbarchartseries.h>
10 10 #include <qstackedbarchartseries.h>
11 11 #include <qpercentbarchartseries.h>
12 12 #include <QPushButton>
13 13 #include <QComboBox>
14 14 #include <QSpinBox>
15 15 #include <QCheckBox>
16 16 #include <QGridLayout>
17 17 #include <QHBoxLayout>
18 18 #include <QLabel>
19 19 #include <QSpacerItem>
20 20 #include <QMessageBox>
21 21 #include <cmath>
22 22 #include <QDebug>
23 23 #include <QStandardItemModel>
24 24
25 25
26 26 QTCOMMERCIALCHART_USE_NAMESPACE
27 27
28 28 MainWidget::MainWidget(QWidget *parent) :
29 29 QWidget(parent)
30 30 {
31 31 m_chartWidget = new QChartView(this);
32 32 m_chartWidget->setRubberBandPolicy(QChartView::HorizonalRubberBand);
33 33
34 34 // Grid layout for the controls for configuring the chart widget
35 35 QGridLayout *grid = new QGridLayout();
36 36 QPushButton *addSeriesButton = new QPushButton("Add series");
37 37 connect(addSeriesButton, SIGNAL(clicked()), this, SLOT(addSeries()));
38 38 grid->addWidget(addSeriesButton, 0, 1);
39 39 initBackroundCombo(grid);
40 40 initScaleControls(grid);
41 41 initThemeCombo(grid);
42 42 QCheckBox *zoomCheckBox = new QCheckBox("Drag'n drop Zoom");
43 43 connect(zoomCheckBox, SIGNAL(toggled(bool)), m_chartWidget, SLOT(setZoomEnabled(bool)));
44 44 zoomCheckBox->setChecked(true);
45 45 grid->addWidget(zoomCheckBox, grid->rowCount(), 0);
46 46 // add row with empty label to make all the other rows static
47 47 grid->addWidget(new QLabel(""), grid->rowCount(), 0);
48 48 grid->setRowStretch(grid->rowCount() - 1, 1);
49 49
50 50 // Another grid layout as a main layout
51 51 QGridLayout *mainLayout = new QGridLayout();
52 52 mainLayout->addLayout(grid, 0, 0);
53 53
54 54 // Init series type specific controls
55 55 initPieControls();
56 56 mainLayout->addLayout(m_pieLayout, 2, 0);
57 57 // Scatter series specific settings
58 58 // m_scatterLayout = new QGridLayout();
59 59 // m_scatterLayout->addWidget(new QLabel("scatter"), 0, 0);
60 60 // m_scatterLayout->setEnabled(false);
61 61 // mainLayout->addLayout(m_scatterLayout, 1, 0);
62 62
63 63 // Add layouts and the chart widget to the main layout
64 64 mainLayout->addWidget(m_chartWidget, 0, 1, 3, 1);
65 65 setLayout(mainLayout);
66
67 // force an update to test data
68 testDataChanged(0);
69 66 }
70 67
71 68 // Combo box for selecting the chart's background
72 69 void MainWidget::initBackroundCombo(QGridLayout *grid)
73 70 {
74 71 QComboBox *backgroundCombo = new QComboBox(this);
75 72 backgroundCombo->addItem("Color");
76 73 backgroundCombo->addItem("Gradient");
77 74 backgroundCombo->addItem("Image");
78 75 connect(backgroundCombo, SIGNAL(currentIndexChanged(int)),
79 76 this, SLOT(backgroundChanged(int)));
80 77
81 78 grid->addWidget(new QLabel("Background:"), grid->rowCount(), 0);
82 79 grid->addWidget(backgroundCombo, grid->rowCount() - 1, 1);
83 80 }
84 81
85 82 // Scale related controls (auto-scale vs. manual min-max values)
86 83 void MainWidget::initScaleControls(QGridLayout *grid)
87 84 {
88 85 m_autoScaleCheck = new QCheckBox("Automatic scaling");
89 86 connect(m_autoScaleCheck, SIGNAL(stateChanged(int)), this, SLOT(autoScaleChanged(int)));
90 87 // Allow setting also non-sense values (like -2147483648 and 2147483647)
91 88 m_xMinSpin = new QSpinBox();
92 89 m_xMinSpin->setMinimum(INT_MIN);
93 90 m_xMinSpin->setMaximum(INT_MAX);
94 91 m_xMinSpin->setValue(0);
95 92 connect(m_xMinSpin, SIGNAL(valueChanged(int)), this, SLOT(xMinChanged(int)));
96 93 m_xMaxSpin = new QSpinBox();
97 94 m_xMaxSpin->setMinimum(INT_MIN);
98 95 m_xMaxSpin->setMaximum(INT_MAX);
99 96 m_xMaxSpin->setValue(10);
100 97 connect(m_xMaxSpin, SIGNAL(valueChanged(int)), this, SLOT(xMaxChanged(int)));
101 98 m_yMinSpin = new QSpinBox();
102 99 m_yMinSpin->setMinimum(INT_MIN);
103 100 m_yMinSpin->setMaximum(INT_MAX);
104 101 m_yMinSpin->setValue(0);
105 102 connect(m_yMinSpin, SIGNAL(valueChanged(int)), this, SLOT(yMinChanged(int)));
106 103 m_yMaxSpin = new QSpinBox();
107 104 m_yMaxSpin->setMinimum(INT_MIN);
108 105 m_yMaxSpin->setMaximum(INT_MAX);
109 106 m_yMaxSpin->setValue(10);
110 107 connect(m_yMaxSpin, SIGNAL(valueChanged(int)), this, SLOT(yMaxChanged(int)));
111 108
112 109 grid->addWidget(m_autoScaleCheck, grid->rowCount(), 0);
113 110 grid->addWidget(new QLabel("x min:"), grid->rowCount(), 0);
114 111 grid->addWidget(m_xMinSpin, grid->rowCount() - 1, 1);
115 112 grid->addWidget(new QLabel("x max:"), grid->rowCount(), 0);
116 113 grid->addWidget(m_xMaxSpin, grid->rowCount() - 1, 1);
117 114 grid->addWidget(new QLabel("y min:"), grid->rowCount(), 0);
118 115 grid->addWidget(m_yMinSpin, grid->rowCount() - 1, 1);
119 116 grid->addWidget(new QLabel("y max:"), grid->rowCount(), 0);
120 117 grid->addWidget(m_yMaxSpin, grid->rowCount() - 1, 1);
121 118
122 119 m_autoScaleCheck->setChecked(true);
123 120 }
124 121
125 122 // Combo box for selecting theme
126 123 void MainWidget::initThemeCombo(QGridLayout *grid)
127 124 {
128 125 QComboBox *chartTheme = new QComboBox();
129 126 chartTheme->addItem("Default");
130 127 chartTheme->addItem("Vanilla");
131 128 chartTheme->addItem("Icy");
132 129 chartTheme->addItem("Grayscale");
133 130 chartTheme->addItem("Scientific");
134 131 chartTheme->addItem("Unnamed1");
135 132 connect(chartTheme, SIGNAL(currentIndexChanged(int)),
136 133 this, SLOT(changeChartTheme(int)));
137 134 grid->addWidget(new QLabel("Chart theme:"), 8, 0);
138 135 grid->addWidget(chartTheme, 8, 1);
139 136 }
140 137
141 138 void MainWidget::initPieControls()
142 139 {
143 140 // Pie series specific settings
144 141 // Pie size factory
145 142 QDoubleSpinBox *pieSizeSpin = new QDoubleSpinBox();
146 143 pieSizeSpin->setMinimum(LONG_MIN);
147 144 pieSizeSpin->setMaximum(LONG_MAX);
148 145 pieSizeSpin->setValue(1.0);
149 146 pieSizeSpin->setSingleStep(0.1);
150 147 connect(pieSizeSpin, SIGNAL(valueChanged(double)), this, SLOT(setPieSizeFactor(double)));
151 148 // Pie position
152 149 QComboBox *piePosCombo = new QComboBox(this);
153 150 piePosCombo->addItem("Maximized");
154 151 piePosCombo->addItem("Top left");
155 152 piePosCombo->addItem("Top right");
156 153 piePosCombo->addItem("Bottom left");
157 154 piePosCombo->addItem("Bottom right");
158 155 connect(piePosCombo, SIGNAL(currentIndexChanged(int)),
159 156 this, SLOT(setPiePosition(int)));
160 157 m_pieLayout = new QGridLayout();
161 158 m_pieLayout->setEnabled(false);
162 159 m_pieLayout->addWidget(new QLabel("Pie size factor"), 0, 0);
163 160 m_pieLayout->addWidget(pieSizeSpin, 0, 1);
164 161 m_pieLayout->addWidget(new QLabel("Pie position"), 1, 0);
165 162 m_pieLayout->addWidget(piePosCombo, 1, 1);
166 163 }
167 164
168 165 void MainWidget::addSeries()
169 166 {
170 167 DataSerieDialog dialog(m_defaultSeriesName, this);
171 connect(&dialog, SIGNAL(accepted(QString, QString)), this, SLOT(addSeries(QString, QString)));
168 connect(&dialog, SIGNAL(accepted(QString, int, int, QString, bool)),
169 this, SLOT(addSeries(QString, int, int, QString, bool)));
172 170 dialog.exec();
173 171 }
174 172
175 void MainWidget::addSeries(QString series, QString data)
173 QList<RealList> MainWidget::generateTestData(int columnCount, int rowCount, QString dataCharacteristics)
176 174 {
177 qDebug() << "addSeries: " << series << " data: " << data;
178 m_defaultSeriesName = series;
179
180 // TODO: a dedicated data class for storing x and y values
181 QList<qreal> x;
182 QList<qreal> y;
183
184 QBarSet *set0 = new QBarSet;
185 QBarSet *set1 = new QBarSet;
186 QBarSet *set2 = new QBarSet;
187 QBarSet *set3 = new QBarSet;
188 QBarSet *set4 = new QBarSet;
189
190 if (data == "linear") {
191 for (int i = 0; i < 20; i++) {
192 x.append(i);
193 y.append(i);
175 // TODO: dataCharacteristics
176 QList<RealList> testData;
177 for (int j(0); j < columnCount; j++) {
178 QList <qreal> newColumn;
179 for (int i(0); i < rowCount; i++) {
180 if (dataCharacteristics == "Sin") {
181 newColumn.append(abs(sin(3.14159265358979 / 50 * i) * 100));
182 } else if (dataCharacteristics == "Sin + random") {
183 newColumn.append(abs(sin(3.14159265358979 / 50 * i) * 100) + (rand() % 5));
184 } else if (dataCharacteristics == "Random") {
185 newColumn.append(rand() % 5);
186 } else if (dataCharacteristics == "Linear") {
187 //newColumn.append(i * (j + 1.0));
188 // TODO: temporary hack to make pie work; prevent zero values:
189 newColumn.append(i * (j + 1.0) + 0.1);
190 } else { // "constant"
191 newColumn.append((j + 1.0));
192 }
194 193 }
195 } else if (data == "linear, 1M") {
196 // 1 million data points from 0.0001 to 100
197 // TODO: What is the requirement? Should we be able to show this kind of data with
198 // reasonable performance, or can we expect the application developer to do "data mining"
199 // for us, so that the count of data points given to QtCommercial Chart is always
200 // reasonable?
201 for (qreal i = 0; i < 100; i += 0.0001) {
202 x.append(i);
203 y.append(20);
194 testData.append(newColumn);
195 }
196 return testData;
197 }
198
199 QStringList MainWidget::generateLabels(int count)
200 {
201 QStringList result;
202 for (int i(0); i < count; i++)
203 result.append("label" + QString::number(i));
204 return result;
205 }
206
207 void MainWidget::addSeries(QString seriesName, int columnCount, int rowCount, QString dataCharacteristics, bool labelsEnabled)
208 {
209 qDebug() << "addSeries: " << seriesName
210 << " columnCount: " << columnCount
211 << " rowCount: " << rowCount
212 << " dataCharacteristics: " << dataCharacteristics
213 << " labels enabled: " << labelsEnabled;
214 m_defaultSeriesName = seriesName;
215
216 QList<RealList> data = generateTestData(columnCount, rowCount, dataCharacteristics);
217
218 // Line series and scatter series use similar data
219 if (seriesName.contains("line", Qt::CaseInsensitive)) {
220 for (int j(0); j < data.count(); j ++) {
221 QList<qreal> column = data.at(j);
222 QLineChartSeries *series = new QLineChartSeries();
223 for (int i(0); i < column.count(); i++) {
224 series->add(i, column.at(i));
225 }
226 m_chartWidget->addSeries(series);
227 setCurrentSeries(series);
204 228 }
205 } else if (data == "SIN") {
206 for (int i = 0; i < 100; i++) {
207 x.append(i);
208 y.append(abs(sin(3.14159265358979 / 50 * i) * 100));
229 } else if (seriesName.contains("scatter", Qt::CaseInsensitive)) {
230 for (int j(0); j < data.count(); j++) {
231 QList<qreal> column = data.at(j);
232 QScatterSeries *series = new QScatterSeries();
233 for (int i(0); i < column.count(); i++) {
234 (*series) << QPointF(i, column.at(i));
235 }
236 m_chartWidget->addSeries(series);
237 setCurrentSeries(series);
209 238 }
210 } else if (data == "SIN + random") {
211 for (qreal i = 0; i < 100; i += 0.1) {
212 x.append(i + (rand() % 5));
213 y.append(abs(sin(3.14159265358979 / 50 * i) * 100) + (rand() % 5));
239 } else if (seriesName.contains("pie", Qt::CaseInsensitive)) {
240 QStringList labels = generateLabels(rowCount);
241 for (int j(0); j < data.count(); j++) {
242 QPieSeries *series = new QPieSeries();
243 QList<qreal> column = data.at(j);
244 for (int i(0); i < column.count(); i++) {
245 series->add(column.at(i), labels.at(i));
246 }
247 m_chartWidget->addSeries(series);
248 setCurrentSeries(series);
214 249 }
215 } else if (data == "Table, 5 series"){
216 // Create some test data to chart
217 *set0 << 1 << 2 << 3 << 4 << 5 << 6 << 7 << 8 << 9 << 10 << 11 << 12;
218 *set1 << 5 << 0 << 0 << 4 << 0 << 7 << 8 << 9 << 9 << 0 << 4 << 2;
219 *set2 << 3 << 5 << 8 << 13 << 8 << 5 << 3 << 2 << 1 << 1 << 3 << 5;
220 *set3 << 5 << 6 << 7 << 3 << 4 << 5 << 8 << 9 << 10 << 5 << 2 << 7;
221 *set4 << 9 << 7 << 5 << 3 << 1 << 2 << 4 << 6 << 8 << 10 << 1 << 6;
222 } else {
223 // TODO: check if data has a valid file name
224 Q_ASSERT(false);
225 }
226
227 // TODO: color of the series
228 QChartSeries *newSeries = 0;
229 if (series == "Scatter") {
230 QScatterSeries *scatter = new QScatterSeries();
231 for (int i(0); i < x.count() && i < y.count(); i++)
232 (*scatter) << QPointF(x.at(i), y.at(i));
233 m_chartWidget->addSeries(scatter);
234 } else if (series == "Pie") {
235 newSeries = new QPieSeries();
236 m_chartWidget->addSeries(newSeries);
237 Q_ASSERT(newSeries->setData(y));
238 } else if (series == "Line") {
239 // TODO: adding data to an existing line series does not give any visuals for some reason
240 // newSeries = m_chartWidget->createSeries(QChartSeries::SeriesTypeLine);
241 // QXYChartSeries *lineSeries = static_cast<QXYChartSeries *>(newSeries);
242 // lineSeries->setColor(Qt::blue);
243 // for (int i(0); i < x.count() && i < y.count(); i++) {
244 // lineSeries->add(x.at(i), y.at(i));
245 // }
246 //Q_ASSERT(newSeries->setData(x, y));
247 QLineChartSeries* series0 = new QLineChartSeries();
248 for (int i(0); i < x.count() && i < y.count(); i++)
249 series0->add(x.at(i), y.at(i));
250 m_chartWidget->addSeries(series0);
251 newSeries = series0;
252 } else if (series == "Bar") {
253 qDebug() << "Bar chart series";
254
255 QBarCategory *category = new QBarCategory;
256 *category << "Jan" << "Feb" << "Mar" << "Apr" << "May" << "June" << "Jul" << "Aug" << "Sep" << "Oct" << "Nov" << "Dec";
257
258 QBarChartSeries* series0 = new QBarChartSeries(category, this);
259
260 series0->addBarSet(set0);
261 series0->addBarSet(set1);
262 series0->addBarSet(set2);
263 series0->addBarSet(set3);
264 series0->addBarSet(set4);
265
266 m_chartWidget->addSeries(series0);
267 newSeries = series0;
268 } else if (series == "StackedBar") {
269 qDebug() << "Stacked bar chart series";
270
271 QBarCategory *category = new QBarCategory;
272 *category << "Jan" << "Feb" << "Mar" << "Apr" << "May" << "June" << "Jul" << "Aug" << "Sep" << "Oct" << "Nov" << "Dec";
273
274 QStackedBarChartSeries* series0 = new QStackedBarChartSeries(category, this);
275
276 series0->addBarSet(set0);
277 series0->addBarSet(set1);
278 series0->addBarSet(set2);
279 series0->addBarSet(set3);
280 series0->addBarSet(set4);
281
282 m_chartWidget->addSeries(series0);
283 newSeries = series0;
284 } else if (series == "PercentBar") {
285 qDebug() << "Percent bar chart series";
286
287 QBarCategory *category = new QBarCategory;
288 *category << "Jan" << "Feb" << "Mar" << "Apr" << "May" << "June" << "Jul" << "Aug" << "Sep" << "Oct" << "Nov" << "Dec";
289
290 QPercentBarChartSeries* series0 = new QPercentBarChartSeries(category, this);
291
292 series0->addBarSet(set0);
293 series0->addBarSet(set1);
294 series0->addBarSet(set2);
295 series0->addBarSet(set3);
296 series0->addBarSet(set4);
297
298 m_chartWidget->addSeries(series0);
299 newSeries = series0;
300 } else {
301 qDebug() << "Something weird going on in MainWidget::addSeries";
302 250 }
303 251
304 setCurrentSeries(newSeries);
252 // TODO: bar and other...
305 253 }
306 254
307 255 void MainWidget::setCurrentSeries(QChartSeries *series)
308 256 {
309 257 if (series) {
310 258 m_currentSeries = series;
311 259 switch (m_currentSeries->type()) {
312 260 case QChartSeries::SeriesTypeLine:
313 261 break;
314 262 case QChartSeries::SeriesTypeScatter:
315 263 break;
316 264 case QChartSeries::SeriesTypePie:
317 265 break;
318 266 case QChartSeries::SeriesTypeBar:
319 267 qDebug() << "setCurrentSeries (bar)";
320 268 break;
321 269 case QChartSeries::SeriesTypeStackedBar:
322 270 qDebug() << "setCurrentSeries (Stackedbar)";
323 271 break;
324 272 case QChartSeries::SeriesTypePercentBar:
325 273 qDebug() << "setCurrentSeries (Percentbar)";
326 274 break;
327 275 default:
328 276 Q_ASSERT(false);
329 277 break;
330 278 }
331 279 }
332 280 }
333 281
334 void MainWidget::testDataChanged(int itemIndex)
335 {
336 qDebug() << "testDataChanged: " << itemIndex;
337
338 // switch (itemIndex) {
339 // case 0: {
340 // QList<QChartDataPoint> data;
341 // for (int x = 0; x < 20; x++) {
342 // data.append(QChartDataPoint() << x << x / 2);
343 // }
344 // m_chartWidget->setData(data);
345 // break;
346 // }
347 // case 1: {
348 // QList<QChartDataPoint> data;
349 // for (int x = 0; x < 100; x++) {
350 // data.append(QChartDataPoint() << x - 200 << 2 * (uint(sin(3.14159/50*x)*80) % 100));
351 // }
352 // m_chartWidget->setData(data);
353 // break;
354 // }
355 // case 2: {
356 // QList<QChartDataPoint> data;
357 // for (int x = 0; x < 1000; x++) {
358 // data.append(QChartDataPoint() << x - 200 << 2 * (uint(sin(3.14159/50*x)*80) % 100) + (rand() % 100 * 0.2));
359 // data.append(QChartDataPoint() << x - 200 << 2 * (uint(sin(3.14159/50*x)*80) % 100) + (rand() % 100 * 0.2));
360 // data.append(QChartDataPoint() << x - 200 << 2 * (uint(sin(3.14159/50*x)*80) % 100) + (rand() % 100 * 0.2));
361 // }
362 // m_chartWidget->setData(data);
363 // break;
364 // }
365 // default:
366 // break;
367 // }
368 }
369
370 282 void MainWidget::backgroundChanged(int itemIndex)
371 283 {
372 284 qDebug() << "backgroundChanged: " << itemIndex;
373 285 }
374 286
375 287 void MainWidget::autoScaleChanged(int value)
376 288 {
377 289 if (value) {
378 290 // TODO: enable auto scaling
379 291 } else {
380 292 // TODO: set scaling manually (and disable auto scaling)
381 293 }
382 294
383 295 m_xMinSpin->setEnabled(!value);
384 296 m_xMaxSpin->setEnabled(!value);
385 297 m_yMinSpin->setEnabled(!value);
386 298 m_yMaxSpin->setEnabled(!value);
387 299 }
388 300
389 301 void MainWidget::xMinChanged(int value)
390 302 {
391 303 qDebug() << "xMinChanged: " << value;
392 304 }
393 305
394 306 void MainWidget::xMaxChanged(int value)
395 307 {
396 308 qDebug() << "xMaxChanged: " << value;
397 309 }
398 310
399 311 void MainWidget::yMinChanged(int value)
400 312 {
401 313 qDebug() << "yMinChanged: " << value;
402 314 }
403 315
404 316 void MainWidget::yMaxChanged(int value)
405 317 {
406 318 qDebug() << "yMaxChanged: " << value;
407 319 }
408 320
409 321 void MainWidget::changeChartTheme(int themeIndex)
410 322 {
411 323 qDebug() << "changeChartTheme: " << themeIndex;
412 324 m_chartWidget->setChartTheme((QChart::ChartTheme) themeIndex);
413 325 //TODO: remove this hack. This is just to make it so that theme change is seen immediately.
414 326 QSize s = size();
415 327 s.setWidth(s.width()+1);
416 328 resize(s);
417 329 }
418 330
419 331 void MainWidget::setPieSizeFactor(double size)
420 332 {
421 333 QPieSeries *pie = qobject_cast<QPieSeries *>(m_currentSeries);
422 334 if (pie)
423 335 pie->setSizeFactor(qreal(size));
424 336 }
425 337
426 338 void MainWidget::setPiePosition(int position)
427 339 {
428 340 QPieSeries *pie = qobject_cast<QPieSeries *>(m_currentSeries);
429 341 if (pie)
430 342 pie->setPosition((QPieSeries::PiePosition) position);
431 343 }
@@ -1,56 +1,59
1 1 #ifndef MAINWIDGET_H
2 2 #define MAINWIDGET_H
3 3
4 4 #include <qchartglobal.h>
5 5 #include <qchartview.h>
6 6 #include <QWidget>
7 7
8 8 class QSpinBox;
9 9 class QCheckBox;
10 10 class QGridLayout;
11 11
12 12 QTCOMMERCIALCHART_USE_NAMESPACE
13 13
14 #define RealList QList<qreal>
15
14 16 class MainWidget : public QWidget
15 17 {
16 18 Q_OBJECT
17 19 public:
18 20 explicit MainWidget(QWidget *parent = 0);
19 21
20 22 signals:
21 23
22 24 private:
23 25 void initBackroundCombo(QGridLayout *grid);
24 26 void initScaleControls(QGridLayout *grid);
25 27 void initThemeCombo(QGridLayout *grid);
26 28 void initPieControls();
27 29
28 30 private slots:
29 31 void addSeries();
30 void addSeries(QString series, QString data);
31 void testDataChanged(int itemIndex);
32 void addSeries(QString series, int columnCount, int rowCount, QString dataCharacteristics, bool labelsEnabled);
32 33 void backgroundChanged(int itemIndex);
33 34 void autoScaleChanged(int value);
34 35 void xMinChanged(int value);
35 36 void xMaxChanged(int value);
36 37 void yMinChanged(int value);
37 38 void yMaxChanged(int value);
38 39 void setCurrentSeries(QChartSeries *series);
39 40 void changeChartTheme(int themeIndex);
40 41 void setPieSizeFactor(double margin);
41 42 void setPiePosition(int position);
43 QList<RealList> generateTestData(int columnCount, int rowCount, QString dataCharacteristics);
44 QStringList generateLabels(int count);
42 45
43 46 private:
44 47 QChartView *m_chartWidget;
45 48 QCheckBox *m_autoScaleCheck;
46 49 QSpinBox *m_xMinSpin;
47 50 QSpinBox *m_xMaxSpin;
48 51 QSpinBox *m_yMinSpin;
49 52 QSpinBox *m_yMaxSpin;
50 53 QString m_defaultSeriesName;
51 54 QChartSeries *m_currentSeries;
52 55 QGridLayout *m_scatterLayout;
53 56 QGridLayout *m_pieLayout;
54 57 };
55 58
56 59 #endif // MAINWIDGET_H
General Comments 0
You need to be logged in to leave comments. Login now