##// END OF EJS Templates
QXYSeries: support for adding data to model when using custom mapping
Marek Rosa -
r1054:e65f6f3d183f
parent child
Show More
@@ -1,133 +1,146
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "qabstractseries.h"
22 22 #include "qabstractseries_p.h"
23 23
24 24 QTCOMMERCIALCHART_BEGIN_NAMESPACE
25 25
26 26 /*!
27 27 \class QAbstractSeries
28 28 \brief Base class for all QtCommercial Chart series.
29 29 \mainclass
30 30
31 31 Usually you use the series type specific inherited classes instead of the base class.
32 32 \sa QXYSeries, QLineSeries, QSplineSeries, QScatterSeries, QAreaSeries, QBarSeries, QStackedBarSeries,
33 33 QPercentBarSeries, QPieSeries
34 34 */
35 35
36 36 /*!
37 37 \enum QAbstractSeries::QSeriesType
38 38
39 39 The type of the series object.
40 40
41 41 \value SeriesTypeLine
42 42 \value SeriesTypeArea
43 43 \value SeriesTypeBar
44 44 \value SeriesTypeStackedBar
45 45 \value SeriesTypePercentBar
46 46 \value SeriesTypePie
47 47 \value SeriesTypeScatter
48 48 \value SeriesTypeSpline
49 49 */
50 50
51 51 /*!
52 52 \fn QSeriesType QAbstractSeries::type() const
53 53 \brief The type of the series.
54 54 */
55 55
56 56 /*!
57 57 \fn bool QAbstractSeries::setModel(QAbstractItemModel *model)
58 58 \brief Use the \a model to provide data for the series. The model overrides possible user data
59 59 set with QChartSeries type specific data setters. For example if you call both
60 60 QScatterSeries::addData() and QScatterSeries::setModel, only the data provided by the model is
61 61 used by the series. Returns true if the model is valid for the series.
62 62 */
63 63
64 64 /*!
65 65 \property QAbstractSeries::name
66 66 \brief name of the series property
67 67 */
68 68
69 69 /*!
70 70 \fn void QAbstractSeries::setName(const QString& name)
71 71 \brief Sets a \a name for the series.
72 72
73 73 The name of a series is shown in the legend for QXYSeries.
74 74 \sa QChart::setTitle()
75 75 \sa QPieSlice::setLabel()
76 76 \sa QBarSet::setName()
77 77 */
78 78
79 79 /*!
80 80 \internal
81 81 \brief Constructs ChartSeries object with \a parent.
82 82 */
83 83 QAbstractSeries::QAbstractSeries(QAbstractSeriesPrivate &d, QObject *parent) :
84 84 QObject(parent),
85 85 d_ptr(&d)
86 86 {
87 87 }
88 88
89 89 /*!
90 90 \brief Virtual destructor for the chart series.
91 91 */
92 92 QAbstractSeries::~QAbstractSeries()
93 93 {
94 94 }
95 95
96 96 /*!
97 97 \brief Returns the pointer to the model that is used as the series data source
98 98 */
99 99 QAbstractItemModel* QAbstractSeries::model() const
100 100 {
101 101 return d_ptr->m_model;
102 102 }
103 103
104 int QAbstractSeries::mapFirst() const
105 {
106 return d_ptr->m_mapFirst;
107 }
108 int QAbstractSeries::mapCount() const
109 {
110 return d_ptr->m_mapCount;
111 }
112
104 113 void QAbstractSeries::setName(const QString& name)
105 114 {
106 115 d_ptr->m_name = name;
107 116 }
108 117
109 118 /*!
110 119 \brief Returns the name of the series.
111 120 \sa setName()
112 121 */
113 122 QString QAbstractSeries::name() const
114 123 {
115 124 return d_ptr->m_name;
116 125 }
117 126
118 127 ///////////////////////////////////////////////////////////////////////////////////////////////////
119 128
120 QAbstractSeriesPrivate::QAbstractSeriesPrivate(QAbstractSeries* q): q_ptr(q),m_model(0)
129 QAbstractSeriesPrivate::QAbstractSeriesPrivate(QAbstractSeries* q):
130 q_ptr(q),
131 m_model(0),
132 m_mapFirst(0),
133 m_mapCount(-1)
121 134 {
122 135 }
123 136
124 137 QAbstractSeriesPrivate::~QAbstractSeriesPrivate()
125 138 {
126 139 }
127 140
128 141 #include "moc_qabstractseries.cpp"
129 142 #include "moc_qabstractseries_p.cpp"
130 143
131 144 QTCOMMERCIALCHART_END_NAMESPACE
132 145
133 146
@@ -1,72 +1,74
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #ifndef QABSTRACTSERIES_H
22 22 #define QABSTRACTSERIES_H
23 23
24 24 #include <qchartglobal.h>
25 25 #include <QObject>
26 26 #include <QPen>
27 27
28 28 class QAbstractItemModel;
29 29
30 30 QTCOMMERCIALCHART_BEGIN_NAMESPACE
31 31
32 32 class QAbstractSeriesPrivate;
33 33
34 34 class QTCOMMERCIALCHART_EXPORT QAbstractSeries : public QObject
35 35 {
36 36 Q_OBJECT
37 37 Q_PROPERTY(QString name READ name WRITE setName)
38 38 Q_ENUMS(QSeriesType)
39 39
40 40 public:
41 41 enum QSeriesType {
42 42 SeriesTypeLine,
43 43 SeriesTypeArea,
44 44 SeriesTypeBar,
45 45 SeriesTypeStackedBar,
46 46 SeriesTypePercentBar,
47 47 SeriesTypePie,
48 48 SeriesTypeScatter,
49 49 SeriesTypeSpline
50 50 };
51 51
52 52 protected:
53 53 QAbstractSeries(QAbstractSeriesPrivate &d, QObject *parent = 0);
54 54
55 55 public:
56 56 ~QAbstractSeries();
57 57 virtual QSeriesType type() const = 0;
58 58 virtual bool setModel(QAbstractItemModel* model) = 0;
59 59 QAbstractItemModel* model() const;
60 int mapFirst() const;
61 int mapCount() const;
60 62 void setName(const QString& name);
61 63 QString name() const;
62 64
63 65 protected:
64 66 QScopedPointer<QAbstractSeriesPrivate> d_ptr;
65 67 friend class ChartDataSet;
66 68 friend class ChartPresenter;
67 69 friend class QLegendPrivate;
68 70 };
69 71
70 72 QTCOMMERCIALCHART_END_NAMESPACE
71 73
72 74 #endif
@@ -1,66 +1,68
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 // W A R N I N G
22 22 // -------------
23 23 //
24 24 // This file is not part of the QtCommercial Chart API. It exists purely as an
25 25 // implementation detail. This header file may change from version to
26 26 // version without notice, or even be removed.
27 27 //
28 28 // We mean it.
29 29
30 30 #ifndef QABSTRACTSERIES_P_H
31 31 #define QABSTRACTSERIES_P_H
32 32
33 33 #include "qabstractseries.h"
34 34
35 35 class QAbstractItemModel;
36 36
37 37 QTCOMMERCIALCHART_BEGIN_NAMESPACE
38 38
39 39 class Domain;
40 40 class ChartPresenter;
41 41 class Chart;
42 42 class LegendMarker;
43 43 class QLegend;
44 44
45 45 class QAbstractSeriesPrivate : public QObject
46 46 {
47 47 Q_OBJECT
48 48 public:
49 49 QAbstractSeriesPrivate(QAbstractSeries *q);
50 50 ~QAbstractSeriesPrivate();
51 51
52 52 virtual void scaleDomain(Domain& domain) = 0;
53 53 virtual Chart* createGraphics(ChartPresenter* presenter) = 0;
54 54 virtual QList<LegendMarker*> createLegendMarker(QLegend* legend) = 0;
55 55
56 56 protected:
57 57 QAbstractSeries *q_ptr;
58 58 QAbstractItemModel *m_model;
59 int m_mapFirst;
60 int m_mapCount;
59 61 QString m_name;
60 62
61 63 friend class QAbstractSeries;
62 64 };
63 65
64 66 QTCOMMERCIALCHART_END_NAMESPACE
65 67
66 68 #endif
@@ -1,464 +1,504
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "qxyseries.h"
22 22 #include "qxyseries_p.h"
23 23 #include "domain_p.h"
24 24 #include "legendmarker_p.h"
25 25 #include <QAbstractItemModel>
26 26
27 27 QTCOMMERCIALCHART_BEGIN_NAMESPACE
28 28
29 29 /*!
30 30 \class QXYSeries
31 31 \brief The QXYSeries class is a base class for line, spline and scatter series.
32 32 */
33 33
34 34 /*!
35 35 \fn QPen QXYSeries::pen() const
36 36 \brief Returns pen used to draw points for series.
37 37 \sa setPen()
38 38 */
39 39
40 40 /*!
41 41 \fn QBrush QXYSeries::brush() const
42 42 \brief Returns brush used to draw points for series.
43 43 \sa setBrush()
44 44 */
45 45
46 46 /*!
47 47 \fn void QXYSeries::clicked(const QPointF& point)
48 48 \brief Signal is emitted when user clicks the \a point on chart.
49 49 */
50 50
51 51 /*!
52 52 \fn void QXYSeries::selected()
53 53
54 54 The signal is emitted if the user selects/deselects the XY series. The logic for maintaining selections should be
55 55 implemented by the user of QXYSeries API.
56 56 */
57 57
58 58 /*!
59 59 \fn void QXYSeriesPrivate::pointReplaced(int index)
60 60 \brief \internal \a index
61 61 */
62 62
63 63 /*!
64 64 \fn void QXYSeriesPrivate::pointAdded(int index)
65 65 \brief \internal \a index
66 66 */
67 67
68 68 /*!
69 69 \fn void QXYSeriesPrivate::pointRemoved(int index)
70 70 \brief \internal \a index
71 71 */
72 72
73 73 /*!
74 74 \fn void QXYSeriesPrivate::updated()
75 75 \brief \internal
76 76 */
77 77
78 78 /*!
79 79 \internal
80 80
81 81 Constructs empty series object which is a child of \a parent.
82 82 When series object is added to QChartView or QChart instance ownerships is transferred.
83 83 */
84 84 QXYSeries::QXYSeries(QXYSeriesPrivate &d,QObject *parent) : QAbstractSeries(d, parent)
85 85 {
86 86
87 87 }
88 88 /*!
89 89 Destroys the object. Series added to QChartView or QChart instances are owned by those,
90 90 and are deleted when mentioned object are destroyed.
91 91 */
92 92 QXYSeries::~QXYSeries()
93 93 {
94 94 }
95 95
96 96 /*!
97 97 Adds data point \a x \a y to the series. Points are connected with lines on the chart.
98 98 */
99 99 void QXYSeries::append(qreal x,qreal y)
100 100 {
101 101 Q_D(QXYSeries);
102 102 Q_ASSERT(d->m_x.size() == d->m_y.size());
103 103 d->m_x<<x;
104 104 d->m_y<<y;
105 105 emit d->pointAdded(d->m_x.size()-1);
106 106 }
107 107
108 108 /*!
109 109 This is an overloaded function.
110 110 Adds data \a point to the series. Points are connected with lines on the chart.
111 111 */
112 112 void QXYSeries::append(const QPointF &point)
113 113 {
114 114 append(point.x(),point.y());
115 115 }
116 116
117 117 /*!
118 118 This is an overloaded function.
119 119 Adds list of data \a points to the series. Points are connected with lines on the chart.
120 120 */
121 121 void QXYSeries::append(const QList<QPointF> points)
122 122 {
123 123 foreach(const QPointF& point , points) {
124 124 append(point.x(),point.y());
125 125 }
126 126 }
127 127
128 128 /*!
129 129 Modifies \a y value for given \a x a value.
130 130 */
131 131 void QXYSeries::replace(qreal x,qreal y)
132 132 {
133 133 Q_D(QXYSeries);
134 134 int index = d->m_x.indexOf(x);
135 135 d->m_x[index] = x;
136 136 d->m_y[index] = y;
137 137 emit d->pointReplaced(index);
138 138 }
139 139
140 140 /*!
141 141 This is an overloaded function.
142 142 Replaces current y value of for given \a point x value with \a point y value.
143 143 */
144 144 void QXYSeries::replace(const QPointF &point)
145 145 {
146 146 replace(point.x(),point.y());
147 147 }
148 148
149 149 /*!
150 150 Removes first \a x value and related y value.
151 151 */
152 152 void QXYSeries::remove(qreal x)
153 153 {
154 154 Q_D(QXYSeries);
155 155 int index = d->m_x.indexOf(x);
156 156
157 157 if (index == -1) return;
158 158
159 159 d->m_x.remove(index);
160 160 d->m_y.remove(index);
161 161
162 162 emit d->pointRemoved(index);
163 163 }
164 164
165 165 /*!
166 166 Removes current \a x and \a y value.
167 167 */
168 168 void QXYSeries::remove(qreal x,qreal y)
169 169 {
170 170 Q_D(QXYSeries);
171 171 int index =-1;
172 172 do {
173 173 index = d->m_x.indexOf(x,index+1);
174 174 } while (index !=-1 && d->m_y.at(index)!=y);
175 175
176 176 if (index==-1) return;
177 177
178 178 d->m_x.remove(index);
179 179 d->m_y.remove(index);
180 180 emit d->pointRemoved(index);
181 181 }
182 182
183 183 /*!
184 184 Removes current \a point x value. Note \a point y value is ignored.
185 185 */
186 186 void QXYSeries::remove(const QPointF &point)
187 187 {
188 188 remove(point.x(),point.y());
189 189 }
190 190
191 191 /*!
192 192 Removes all data points from the series.
193 193 */
194 194 void QXYSeries::removeAll()
195 195 {
196 196 Q_D(QXYSeries);
197 197 d->m_x.clear();
198 198 d->m_y.clear();
199 199 }
200 200
201 201 /*!
202 202 \internal \a pos
203 203 */
204 204 qreal QXYSeries::x(int pos) const
205 205 {
206 206 Q_D(const QXYSeries);
207 207 if (d->m_model) {
208 208 if (d->m_mapOrientation == Qt::Vertical)
209 209 // consecutive data is read from model's column
210 return d->m_model->data(d->m_model->index(pos, d->m_mapX), Qt::DisplayRole).toDouble();
210 return d->m_model->data(d->m_model->index(pos + d->m_mapFirst, d->m_mapX), Qt::DisplayRole).toDouble();
211 211 else
212 212 // consecutive data is read from model's row
213 return d->m_model->data(d->m_model->index(d->m_mapX, pos), Qt::DisplayRole).toDouble();
213 return d->m_model->data(d->m_model->index(d->m_mapX, pos + d->m_mapFirst), Qt::DisplayRole).toDouble();
214 214 } else {
215 215 // model is not specified, return the data from series' internal data store
216 216 return d->m_x.at(pos);
217 217 }
218 218 }
219 219
220 220 /*!
221 221 \internal \a pos
222 222 */
223 223 qreal QXYSeries::y(int pos) const
224 224 {
225 225 Q_D(const QXYSeries);
226 226 if (d->m_model) {
227 227 if (d->m_mapOrientation == Qt::Vertical)
228 228 // consecutive data is read from model's column
229 return d->m_model->data(d->m_model->index(pos, d->m_mapY), Qt::DisplayRole).toDouble();
229 return d->m_model->data(d->m_model->index(pos + d->m_mapFirst, d->m_mapY), Qt::DisplayRole).toDouble();
230 230 else
231 231 // consecutive data is read from model's row
232 return d->m_model->data(d->m_model->index(d->m_mapY, pos), Qt::DisplayRole).toDouble();
232 return d->m_model->data(d->m_model->index(d->m_mapY, pos + d->m_mapFirst), Qt::DisplayRole).toDouble();
233 233 } else {
234 234 // model is not specified, return the data from series' internal data store
235 235 return d->m_y.at(pos);
236 236 }
237 237 }
238 238
239 239 /*!
240 240 Returns number of data points within series.
241 241 */
242 242 int QXYSeries::count() const
243 243 {
244 244 Q_D(const QXYSeries);
245 245
246 246 Q_ASSERT(d->m_x.size() == d->m_y.size());
247 247
248 248 if (d->m_model) {
249 249 if (d->m_mapOrientation == Qt::Vertical) {
250 // data is in a column. Return the number of mapped items
251 return d->m_model->rowCount();
250 // data is in a column. Return the number of mapped items if the model's column have enough items
251 // or the number of items that can be mapped
252 if (d->m_mapCount != -1)
253 return qMin(d->m_mapCount, qMax(d->m_model->rowCount() - d->m_mapFirst, 0));
254 else
255 return qMax(d->m_model->rowCount() - d->m_mapFirst, 0);
252 256 } else {
253 // data is in a row. Return the number of mapped items
254 return d->m_model->columnCount();
257 // data is in a row. Return the number of mapped items if the model's row have enough items
258 // or the number of items that can be mapped
259 if (d->m_mapCount != -1)
260 return qMin(d->m_mapCount, qMax(d->m_model->columnCount() - d->m_mapFirst, 0));
261 else
262 return qMax(d->m_model->columnCount() - d->m_mapFirst, 0);
255 263 }
256 264 }
257 265
258 266 // model is not specified, return the number of points in the series internal data store
259 267 return d->m_x.size();
260 268 }
261 269
262 270 /*!
263 271 Returns the data points of the series.
264 272 */
265 273 QList<QPointF> QXYSeries::data()
266 274 {
267 275 Q_D(QXYSeries);
268 276 QList<QPointF> data;
269 277 for (int i(0); i < d->m_x.count() && i < d->m_y.count(); i++)
270 278 data.append(QPointF(d->m_x.at(i), d->m_y.at(i)));
271 279 return data;
272 280 }
273 281
274 282
275 283 /*!
276 284 Sets \a pen used for drawing points on the chart. If the pen is not defined, the
277 285 pen from chart theme is used.
278 286 \sa QChart::setTheme()
279 287 */
280 288 void QXYSeries::setPen(const QPen &pen)
281 289 {
282 290 Q_D(QXYSeries);
283 291 if (d->m_pen!=pen) {
284 292 d->m_pen = pen;
285 293 emit d->updated();
286 294 }
287 295 }
288 296
289 297 QPen QXYSeries::pen() const
290 298 {
291 299 Q_D(const QXYSeries);
292 300 return d->m_pen;
293 301 }
294 302
295 303 /*!
296 304 Sets \a brush used for drawing points on the chart. If the brush is not defined, brush
297 305 from chart theme setting is used.
298 306 \sa QChart::setTheme()
299 307 */
300 308 void QXYSeries::setBrush(const QBrush &brush)
301 309 {
302 310 Q_D(QXYSeries);
303 311 if (d->m_brush!=brush) {
304 312 d->m_brush = brush;
305 313 emit d->updated();
306 314 }
307 315 }
308 316
309 317 QBrush QXYSeries::brush() const
310 318 {
311 319 Q_D(const QXYSeries);
312 320 return d->m_brush;
313 321 }
314 322
315 323
316 324 /*!
317 325 Sets if data points are \a visible and should be drawn on line.
318 326 */
319 327 void QXYSeries::setPointsVisible(bool visible)
320 328 {
321 329 Q_D(QXYSeries);
322 330 if (d->m_pointsVisible != visible){
323 331 d->m_pointsVisible = visible;
324 332 emit d->updated();
325 333 }
326 334 }
327 335
328 336 /*!
329 337 Returns true if drawing the data points of the series is enabled.
330 338 */
331 339 bool QXYSeries::pointsVisible() const
332 340 {
333 341 Q_D(const QXYSeries);
334 342 return d->m_pointsVisible;
335 343 }
336 344
337 345
338 346 /*!
339 347 Stream operator for adding a data \a point to the series.
340 348 \sa append()
341 349 */
342 350 QXYSeries& QXYSeries::operator<< (const QPointF &point)
343 351 {
344 352 append(point);
345 353 return *this;
346 354 }
347 355
348 356
349 357 /*!
350 358 Stream operator for adding a list of \a points to the series.
351 359 \sa append()
352 360 */
353 361
354 362 QXYSeries& QXYSeries::operator<< (const QList<QPointF> points)
355 363 {
356 364 append(points);
357 365 return *this;
358 366 }
359 367
360 368 /*!
361 \internal
362 */
363 void QXYSeries::modelUpdated(QModelIndex topLeft, QModelIndex bottomRight)
364 {
365 Q_UNUSED(bottomRight)
366 Q_D(QXYSeries);
367 if (d->m_mapOrientation == Qt::Vertical) {
368 if (topLeft.column() == d->m_mapX || topLeft.column() == d->m_mapY)
369 emit d->pointReplaced(topLeft.row());
370 } else {
371 if (topLeft.row() == d->m_mapX || topLeft.row() == d->m_mapY)
372 emit d->pointReplaced(topLeft.column());
373 }
374 }
375
376 /*!
377 369 \fn bool QXYSeries::setModel(QAbstractItemModel *model)
378 370 Sets the \a model to be used as a data source
379 371 \sa setModelMapping()
380 372 */
381 373 bool QXYSeries::setModel(QAbstractItemModel *model)
382 374 {
383 375 Q_D(QXYSeries);
384 376 // disconnect signals from old model
385 377 if (d->m_model) {
386 378 QObject::disconnect(d->m_model, 0, this, 0);
387 379 d->m_mapX = -1;
388 380 d->m_mapY = -1;
389 381 d->m_mapOrientation = Qt::Vertical;
390 382 }
391 383
392 384 // set new model
393 385 if (model) {
394 386 d->m_model = model;
395 387 return true;
396 388 } else {
397 389 d->m_model = 0;
398 390 return false;
399 391 }
400 392 }
401 393
402 394 /*!
403 395 Sets the \a modelX to be used as a data source for x coordinate and \a modelY to be used
404 396 as a data source for y coordinate. The \a orientation parameter specifies whether the data
405 397 is in columns or in rows.
406 398 \sa setModel()
407 399 */
408 400 void QXYSeries::setModelMapping(int modelX, int modelY, Qt::Orientation orientation)
409 401 {
410 402 Q_D(QXYSeries);
411 403 if (d->m_model == 0)
412 404 return;
413 405 d->m_mapX = modelX;
414 406 d->m_mapY = modelY;
415 407 d->m_mapOrientation = orientation;
416 connect(d->m_model,SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(modelUpdated(QModelIndex,QModelIndex)));
408
409 // connect the signals from the model
410 connect(d->m_model,SIGNAL(dataChanged(QModelIndex,QModelIndex)), d, SLOT(modelUpdated(QModelIndex,QModelIndex)));
411 if (d->m_mapOrientation == Qt::Vertical) {
412 connect(d->m_model,SIGNAL(rowsInserted(QModelIndex,int,int)), d, SLOT(modelDataAdded(QModelIndex,int,int)));
413 connect(d->m_model,SIGNAL(rowsRemoved(QModelIndex,int,int)), d, SLOT(modelDataRemoved(QModelIndex,int,int)));
414 } else {
415 connect(d->m_model, SIGNAL(columnsInserted(QModelIndex,int,int)), d, SLOT(modelDataAdded(QModelIndex,int,int)));
416 connect(d->m_model, SIGNAL(columnsRemoved(QModelIndex,int,int)), d, SLOT(modelDataRemoved(QModelIndex,int,int)));
417 }
418 }
419
420 void QXYSeries::setModelMappingRange(int first, int count)
421 {
422 Q_D(QXYSeries);
423 d->m_mapFirst = first;
424 d->m_mapCount = count;
417 425 }
418 426
419 427 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
420 428
421 429
422 430 QXYSeriesPrivate::QXYSeriesPrivate(QXYSeries *q) : QAbstractSeriesPrivate(q),
423 431 m_mapX(-1),
424 432 m_mapY(-1),
425 433 m_mapOrientation( Qt::Vertical),
426 434 m_pointsVisible(false)
427 435 {
428 436 }
429 437
430 438 void QXYSeriesPrivate::scaleDomain(Domain& domain)
431 439 {
432 440 qreal minX(domain.minX());
433 441 qreal minY(domain.minY());
434 442 qreal maxX(domain.maxX());
435 443 qreal maxY(domain.maxY());
436 444 int tickXCount(domain.tickXCount());
437 445 int tickYCount(domain.tickYCount());
438 446
439 447 Q_Q(QXYSeries);
440 448 for (int i = 0; i < q->count(); i++)
441 449 {
442 450 qreal x = q->x(i);
443 451 qreal y = q->y(i);
444 452 minX = qMin(minX, x);
445 453 minY = qMin(minY, y);
446 454 maxX = qMax(maxX, x);
447 455 maxY = qMax(maxY, y);
448 456 }
449 457
450 458 domain.setRangeX(minX,maxX,tickXCount);
451 459 domain.setRangeY(minY,maxY,tickYCount);
452 460 }
453 461
454 462 QList<LegendMarker*> QXYSeriesPrivate::createLegendMarker(QLegend* legend)
455 463 {
456 464 Q_Q(QXYSeries);
457 465 QList<LegendMarker*> list;
458 466 return list << new XYLegendMarker(q,legend);
459 467 }
460 468
469 void QXYSeriesPrivate::modelUpdated(QModelIndex topLeft, QModelIndex bottomRight)
470 {
471 for (int row = topLeft.row(); row <= bottomRight.row(); row++) {
472 for (int column = topLeft.column(); column <= bottomRight.column(); column++) {
473 if (m_mapOrientation == Qt::Vertical) {
474 if ((column == m_mapX || column == m_mapY) // modified item is in a mapped column
475 && row >= m_mapFirst // modfied item in not before first item
476 && (m_mapCount == -1 || row < m_mapFirst + m_mapCount)) // map is not limited or item lays before the end of map
477 emit pointReplaced(row - m_mapFirst);
478 } else {
479 if ((row == m_mapX || row == m_mapY) // modified item is in a mapped row
480 && column >= m_mapFirst // modfied item in not before first item
481 && (m_mapCount == -1 || column < m_mapFirst + m_mapCount)) // map is not limited or item lays before the end of map
482 emit pointReplaced(column - m_mapFirst);
483 }
484 }
485 }
486 }
487
488
489 void QXYSeriesPrivate::modelDataAdded(QModelIndex parent, int start, int end)
490 {
491 Q_UNUSED(parent);
492 emit pointsAdded(start, end);
493 }
494
495 void QXYSeriesPrivate::modelDataRemoved(QModelIndex parent, int start, int end)
496 {
497 Q_UNUSED(parent);
498 emit pointsRemoved(start, end);
499 }
500
461 501 #include "moc_qxyseries.cpp"
462 502 #include "moc_qxyseries_p.cpp"
463 503
464 504 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,89 +1,90
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #ifndef QXYSERIES_H
22 22 #define QXYSERIES_H
23 23
24 24 #include <qchartglobal.h>
25 25 #include <qabstractseries.h>
26 26 #include <QPen>
27 27 #include <QBrush>
28 28
29 29 class QModelIndex;
30 30
31 31 QTCOMMERCIALCHART_BEGIN_NAMESPACE
32 32
33 33 class QXYSeriesPrivate;
34 34
35 35 class QTCOMMERCIALCHART_EXPORT QXYSeries : public QAbstractSeries
36 36 {
37 37 Q_OBJECT
38 38 protected:
39 39 explicit QXYSeries(QXYSeriesPrivate &d,QObject *parent = 0);
40 40 ~QXYSeries();
41 41
42 42 public:
43 43 void append(qreal x, qreal y);
44 44 void append(const QPointF &point);
45 45 void append(const QList<QPointF> points);
46 46 void replace(qreal x,qreal y);
47 47 void replace(const QPointF &point);
48 48 void remove(qreal x);
49 49 void remove(qreal x, qreal y);
50 50 void remove(const QPointF &point);
51 51 void removeAll();
52 52
53 53 int count() const;
54 54 qreal x(int pos) const;
55 55 qreal y(int pos) const;
56 56 QList<QPointF> data();
57 57
58 58 QXYSeries& operator << (const QPointF &point);
59 59 QXYSeries& operator << (const QList<QPointF> points);
60 60
61 61 void setPen(const QPen &pen);
62 62 QPen pen() const;
63 63
64 64 void setBrush(const QBrush &brush);
65 65 QBrush brush() const;
66 66
67 67 void setPointsVisible(bool visible = true);
68 68 bool pointsVisible() const;
69 69
70 70 bool setModel(QAbstractItemModel *model);
71 71 virtual void setModelMapping(int modelX, int modelY, Qt::Orientation orientation = Qt::Vertical);
72 void setModelMappingRange(int first, int count = -1);
72 73
73 private Q_SLOTS:
74 void modelUpdated(QModelIndex topLeft, QModelIndex bottomRight);
74 //private Q_SLOTS:
75 // void modelUpdated(QModelIndex topLeft, QModelIndex bottomRight);
75 76
76 77 Q_SIGNALS:
77 78 void clicked(const QPointF &point);
78 79 void selected();
79 80
80 81 private:
81 82 Q_DECLARE_PRIVATE(QXYSeries);
82 83 Q_DISABLE_COPY(QXYSeries);
83 84 friend class XYLegendMarker;
84 85 friend class XYChartItem;
85 86 };
86 87
87 88 QTCOMMERCIALCHART_END_NAMESPACE
88 89
89 90 #endif
@@ -1,75 +1,84
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 // W A R N I N G
22 22 // -------------
23 23 //
24 24 // This file is not part of the QtCommercial Chart API. It exists purely as an
25 25 // implementation detail. This header file may change from version to
26 26 // version without notice, or even be removed.
27 27 //
28 28 // We mean it.
29 29
30 30 #ifndef QXYSERIES_P_H
31 31 #define QXYSERIES_P_H
32 32
33 33 #include "qabstractseries_p.h"
34 34
35 35 QTCOMMERCIALCHART_BEGIN_NAMESPACE
36 36
37 37 class QXYSeries;
38 38
39 39 class QXYSeriesPrivate: public QAbstractSeriesPrivate
40 40 {
41 41 Q_OBJECT
42 42
43 43 public:
44 44 QXYSeriesPrivate(QXYSeries* q);
45 45
46 46 void scaleDomain(Domain& domain);
47 47 QList<LegendMarker*> createLegendMarker(QLegend* legend);
48 48
49 private Q_SLOTS:
50 void modelUpdated(QModelIndex topLeft, QModelIndex bottomRight);
51 void modelDataAdded(QModelIndex parent, int start, int end);
52 void modelDataRemoved(QModelIndex parent, int start, int end);
53
49 54 Q_SIGNALS:
50 55 void updated();
51 56 void pointReplaced(int index);
52 57 void pointRemoved(int index);
58 void pointsRemoved(int start, int end);
53 59 void pointAdded(int index);
60 void pointsAdded(int start, int end);
61
62
54 63
55 64 protected:
56 65 QVector<qreal> m_x;
57 66 QVector<qreal> m_y;
58 67
59 68 QPen m_pen;
60 69 QBrush m_brush;
61 70
62 71 int m_mapX;
63 72 int m_mapY;
64 73 Qt::Orientation m_mapOrientation;
65 74 bool m_pointsVisible;
66 75
67 76 private:
68 77 Q_DECLARE_PUBLIC(QXYSeries);
69 78 friend class QScatterSeries;
70 79
71 80 };
72 81
73 82 QTCOMMERCIALCHART_END_NAMESPACE
74 83
75 84 #endif
@@ -1,178 +1,244
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "xychartitem_p.h"
22 22 #include "qxyseries.h"
23 23 #include "qxyseries_p.h"
24 24 #include "chartpresenter_p.h"
25 25 #include "chartanimator_p.h"
26 26 #include <QPainter>
27 27 #include <QGraphicsSceneMouseEvent>
28 28
29 29
30 30 QTCOMMERCIALCHART_BEGIN_NAMESPACE
31 31
32 32 //TODO: optimize : remove points which are not visible
33 33
34 34 XYChartItem::XYChartItem(QXYSeries *series, ChartPresenter *presenter):ChartItem(presenter),
35 35 m_minX(0),
36 36 m_maxX(0),
37 37 m_minY(0),
38 38 m_maxY(0),
39 39 m_series(series)
40 40 {
41 41 connect(series->d_func(),SIGNAL(pointReplaced(int)),this,SLOT(handlePointReplaced(int)));
42 42 connect(series->d_func(),SIGNAL(pointAdded(int)),this,SLOT(handlePointAdded(int)));
43 connect(series->d_func(),SIGNAL(pointsAdded(int, int)),this,SLOT(handlePointsAdded(int, int)));
43 44 connect(series->d_func(),SIGNAL(pointRemoved(int)),this,SLOT(handlePointRemoved(int)));
45 connect(series->d_func(),SIGNAL(pointsRemoved(int, int)),this,SLOT(handlePointsRemoved(int, int)));
44 46 connect(this,SIGNAL(clicked(QPointF)),series,SIGNAL(clicked(QPointF)));
45 47 }
46 48
47 49 QPointF XYChartItem::calculateGeometryPoint(const QPointF &point) const
48 50 {
49 51 const qreal deltaX = m_size.width()/(m_maxX-m_minX);
50 52 const qreal deltaY = m_size.height()/(m_maxY-m_minY);
51 53 qreal x = (point.x() - m_minX)* deltaX;
52 54 qreal y = (point.y() - m_minY)*-deltaY + m_size.height();
53 55 return QPointF(x,y);
54 56 }
55 57
56 58
57 59 QPointF XYChartItem::calculateGeometryPoint(int index) const
58 60 {
59 61 const qreal deltaX = m_size.width()/(m_maxX-m_minX);
60 62 const qreal deltaY = m_size.height()/(m_maxY-m_minY);
61 63 qreal x = (m_series->x(index) - m_minX)* deltaX;
62 64 qreal y = (m_series->y(index) - m_minY)*-deltaY + m_size.height();
63 65 return QPointF(x,y);
64 66 }
65 67
66 68 QVector<QPointF> XYChartItem::calculateGeometryPoints() const
67 69 {
68 70 const qreal deltaX = m_size.width()/(m_maxX-m_minX);
69 71 const qreal deltaY = m_size.height()/(m_maxY-m_minY);
70 72
71 73 QVector<QPointF> points;
72 74 points.reserve(m_series->count());
73 75 for (int i = 0; i < m_series->count(); ++i) {
74 76 qreal x = (m_series->x(i) - m_minX)* deltaX;
75 77 qreal y = (m_series->y(i) - m_minY)*-deltaY + m_size.height();
76 78 points << QPointF(x,y);
77 79 }
78 80 return points;
79 81 }
80 82
81 83 QPointF XYChartItem::calculateDomainPoint(const QPointF &point) const
82 84 {
83 85 const qreal deltaX = m_size.width()/(m_maxX-m_minX);
84 86 const qreal deltaY = m_size.height()/(m_maxY-m_minY);
85 87 qreal x = point.x()/deltaX +m_minX;
86 88 qreal y = (point.y()-m_size.height())/(-deltaY)+ m_minY;
87 89 return QPointF(x,y);
88 90 }
89 91
90 92 void XYChartItem::updateLayout(QVector<QPointF> &oldPoints, QVector<QPointF> &newPoints,int index)
91 93 {
92 94 if (animator()) {
93 95 animator()->updateLayout(this,oldPoints,newPoints,index);
94 96 } else {
95 97 setLayout(newPoints);
96 98 }
97 99 }
98 100
99 101 void XYChartItem::setLayout(QVector<QPointF> &points)
100 102 {
101 103 m_points = points;
102 104 update();
103 105 }
104 106
105 107 //handlers
106 108
107 109 void XYChartItem::handlePointAdded(int index)
108 110 {
109 Q_ASSERT(index<m_series->count());
110 Q_ASSERT(index>=0);
111 if (m_series->model() == 0) {
112 Q_ASSERT(index<m_series->count());
113 Q_ASSERT(index>=0);
114 }
111 115 QVector<QPointF> points = m_points;
112 116 QPointF point;
113 117 point = calculateGeometryPoint(index);
114 118 points.insert(index, point);
115 119 updateLayout(m_points, points, index);
116 120 update();
117 121 }
122
123 void XYChartItem::handlePointsAdded(int start, int end)
124 {
125 if (m_series->model() == 0) {
126 for (int i = start; i <= end; i++)
127 handlePointAdded(i);
128 } else {
129 // series uses model as a data source
130 int first = m_series->mapFirst();
131 int count = m_series->mapCount();
132 int addedCount = end - start + 1;
133 if (count != -1 && start >= first + count) {
134 return;
135 }
136
137 // adding items to unlimited map
138 else if (count == -1 && start >= first) {
139 for (int i = start; i <= end; i++)
140 handlePointAdded(i - first);
141 } else if (count == - 1 && start < first) {
142 // not all newly added items
143 for (int i = first; i < first + addedCount; i++)
144 handlePointAdded(i - first);
145 }
146 // commented out code below does the same thing, but its more confusing.
147 // } else if (count == -1) {
148 // int begin = qMax(start, first);
149 // for (int i = begin; i < begin + (end - start + 1); i++)
150 // handlePointAdded(i - first);
151 // }
152
153 // adding items to limited map
154 else if (start >= first) {
155 // remove the items that will no longer fit into the map
156 // int toRemove = addedCount - (count - points().size());
157 for (int i = start; i <= end; i++) {
158 handlePointAdded(i - first);
159 }
160 if (m_points.size() > count)
161 for (int i = m_points.size() - 1; i >= count; i--)
162 handlePointRemoved(i);
163 // update();
164 } else {
165 //
166 for (int i = first; i < first + addedCount; i++) {
167 handlePointAdded(i - first);
168 }
169 if (m_points.size() > count)
170 for (int i = m_points.size() - 1; i >= count; i--)
171 handlePointRemoved(i);
172 }
173 }
174 }
175
118 176 void XYChartItem::handlePointRemoved(int index)
119 177 {
120 Q_ASSERT(index<m_series->count() + 1);
121 Q_ASSERT(index>=0);
178 if (m_series->model() == 0) {
179 Q_ASSERT(index<m_series->count() + 1);
180 Q_ASSERT(index>=0);
181 }
122 182 QVector<QPointF> points = m_points;
123 183 points.remove(index);
124 184 updateLayout(m_points, points, index);
125 185 update();
126 186 }
127 187
188 void XYChartItem::handlePointsRemoved(int start, int end)
189 {
190 Q_UNUSED(start)
191 Q_UNUSED(end)
192 }
193
128 194 void XYChartItem::handlePointReplaced(int index)
129 195 {
130 196 Q_ASSERT(index<m_series->count());
131 197 Q_ASSERT(index>=0);
132 198 QPointF point = calculateGeometryPoint(index);
133 199 QVector<QPointF> points = m_points;
134 200 points.replace(index,point);
135 201 updateLayout(m_points,points,index);
136 202 update();
137 203 }
138 204
139 205 void XYChartItem::handleDomainChanged(qreal minX, qreal maxX, qreal minY, qreal maxY)
140 206 {
141 207 m_minX=minX;
142 208 m_maxX=maxX;
143 209 m_minY=minY;
144 210 m_maxY=maxY;
145 211
146 212 if (isEmpty()) return;
147 213 QVector<QPointF> points = calculateGeometryPoints();
148 214 updateLayout(m_points,points);
149 215 update();
150 216 }
151 217
152 218 void XYChartItem::handleGeometryChanged(const QRectF &rect)
153 219 {
154 220 Q_ASSERT(rect.isValid());
155 221 m_size=rect.size();
156 222 m_clipRect=rect.translated(-rect.topLeft());
157 223 setPos(rect.topLeft());
158 224
159 225 if (isEmpty()) return;
160 226 QVector<QPointF> points = calculateGeometryPoints();
161 227 updateLayout(m_points,points);
162 228 update();
163 229 }
164 230
165 231
166 232 bool XYChartItem::isEmpty()
167 233 {
168 234 return !m_clipRect.isValid() || qFuzzyIsNull(m_maxX - m_minX) || qFuzzyIsNull(m_maxY - m_minY);
169 235 }
170 236
171 237 void XYChartItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
172 238 {
173 239 emit clicked(calculateDomainPoint(event->pos()));
174 240 }
175 241
176 242 #include "moc_xychartitem_p.cpp"
177 243
178 244 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,85 +1,87
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #ifndef XYCHARTITEM_H
22 22 #define XYCHARTITEM_H
23 23
24 24 #include "qchartglobal.h"
25 25 #include "chartitem_p.h"
26 26 #include <QPen>
27 27
28 28 QTCOMMERCIALCHART_BEGIN_NAMESPACE
29 29
30 30 class ChartPresenter;
31 31 class QXYSeries;
32 32
33 33 class XYChartItem : public ChartItem
34 34 {
35 35 Q_OBJECT
36 36 public:
37 37 explicit XYChartItem(QXYSeries *series, ChartPresenter *presenter);
38 38 ~XYChartItem(){};
39 39
40 40 QVector<QPointF> points() const {return m_points;}
41 41 QRectF clipRect() const { return m_clipRect;}
42 42
43 43
44 44 public Q_SLOTS:
45 45 void handlePointAdded(int index);
46 void handlePointsAdded(int start, int end);
46 47 void handlePointRemoved(int index);
48 void handlePointsRemoved(int start, int end);
47 49 void handlePointReplaced(int index);
48 50 void handleDomainChanged(qreal minX, qreal maxX, qreal minY, qreal maxY);
49 51 void handleGeometryChanged(const QRectF &size);
50 52
51 53 Q_SIGNALS:
52 54 void clicked(const QPointF& point);
53 55
54 56 protected:
55 57
56 58 virtual void setLayout(QVector<QPointF> &points);
57 59 virtual void updateLayout(QVector<QPointF> &oldPoints,QVector<QPointF> &newPoints,int index = 0);
58 60
59 61 QPointF calculateGeometryPoint(const QPointF &point) const;
60 62 QPointF calculateGeometryPoint(int index) const;
61 63 QPointF calculateDomainPoint(const QPointF &point) const;
62 64 QVector<QPointF> calculateGeometryPoints() const;
63 65 void mousePressEvent(QGraphicsSceneMouseEvent *event);
64 66
65 67 private:
66 68 inline bool isEmpty();
67 69
68 70 private:
69 71 qreal m_minX;
70 72 qreal m_maxX;
71 73 qreal m_minY;
72 74 qreal m_maxY;
73 75 QXYSeries* m_series;
74 76 QSizeF m_size;
75 77 QRectF m_clipRect;
76 78 QVector<QPointF> m_points;
77 79
78 80 friend class XYAnimation;
79 81 friend class AreaChartItem;
80 82
81 83 };
82 84
83 85 QTCOMMERCIALCHART_END_NAMESPACE
84 86
85 87 #endif
@@ -1,341 +1,342
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "tablewidget.h"
22 22 #include <QGridLayout>
23 23 #include <QTableView>
24 24 #include <QStyledItemDelegate>
25 25 #include <QLineSeries>
26 26 #include <QSplineSeries>
27 27 #include <QScatterSeries>
28 28 #include "customtablemodel.h"
29 29 #include <QPieSeries>
30 30 #include <QPieSlice>
31 31 #include <QAreaSeries>
32 32 #include <QBarSeries>
33 33 #include <QBarSet>
34 34 #include <QPushButton>
35 35 #include <QRadioButton>
36 36 #include <QLabel>
37 37 #include <QSpinBox>
38 38 #include <QTime>
39 39
40 40 TableWidget::TableWidget(QWidget *parent)
41 41 : QWidget(parent)
42 42 {
43 43 setGeometry(100, 100, 1000, 600);
44 44 qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
45 45 // create simple model for storing data
46 46 // user's table data model
47 47 m_model = new CustomTableModel;
48 48 m_tableView = new QTableView;
49 49 m_tableView->setModel(m_model);
50 50 m_tableView->setMinimumHeight(300);
51 51 // tableView->setMinimumSize(340, 480);
52 52 // tableView->setItemDelegate(new QStyledItemDelegate);
53 53 m_chart = new QChart;
54 54 m_chart->legend()->setVisible(true);
55 // m_chart->setAnimationOptions(QChart::SeriesAnimations);
55 56 m_chartView = new QChartView(m_chart);
56 57 m_chartView->setRenderHint(QPainter::Antialiasing);
57 58 m_chartView->setMinimumSize(640, 480);
58 59
59 60 // add, remove data buttons
60 61 QPushButton* addRowAboveButton = new QPushButton("Add row above");
61 62 connect(addRowAboveButton, SIGNAL(clicked()), this, SLOT(addRowAbove()));
62 63
63 64 QPushButton* addRowBelowButton = new QPushButton("Add row below");
64 65 connect(addRowBelowButton, SIGNAL(clicked()), this, SLOT(addRowBelow()));
65 66
66 67 QPushButton* removeRowButton = new QPushButton("Remove row");
67 68 connect(removeRowButton, SIGNAL(clicked()), this, SLOT(removeRow()));
68 69
69 70 QLabel *spinBoxLabel = new QLabel("Rows affected:");
70 71
71 72 // spin box for setting number of affected items (add, remove)
72 73 m_linesCountSpinBox = new QSpinBox;
73 74 m_linesCountSpinBox->setRange(1, 10);
74 75 m_linesCountSpinBox->setValue(1);
75 76
76 77 // buttons layout
77 78 QVBoxLayout* buttonsLayout = new QVBoxLayout;
78 79 buttonsLayout->addWidget(spinBoxLabel);
79 80 buttonsLayout->addWidget(m_linesCountSpinBox);
80 81 buttonsLayout->addWidget(addRowAboveButton);
81 82 buttonsLayout->addWidget(addRowBelowButton);
82 83 buttonsLayout->addWidget(removeRowButton);
83 84 buttonsLayout->addStretch();
84 85
85 86 // chart type radio buttons
86 87 m_lineRadioButton = new QRadioButton("Line");
87 88 m_splineRadioButton = new QRadioButton("Spline");
88 89 m_scatterRadioButton = new QRadioButton("Scatter");
89 90 m_pieRadioButton = new QRadioButton("Pie");
90 91 m_areaRadioButton = new QRadioButton("Area");
91 92 m_barRadioButton = new QRadioButton("Bar");
92 93
93 94 connect(m_lineRadioButton, SIGNAL(toggled(bool)), this, SLOT(updateChartType(bool)));
94 95 connect(m_splineRadioButton, SIGNAL(toggled(bool)), this, SLOT(updateChartType(bool)));
95 96 connect(m_scatterRadioButton, SIGNAL(toggled(bool)), this, SLOT(updateChartType(bool)));
96 97 connect(m_pieRadioButton, SIGNAL(toggled(bool)), this, SLOT(updateChartType(bool)));
97 98 connect(m_areaRadioButton, SIGNAL(toggled(bool)), this, SLOT(updateChartType(bool)));
98 99 connect(m_barRadioButton, SIGNAL(toggled(bool)), this, SLOT(updateChartType(bool)));
99 100 m_lineRadioButton->setChecked(true);
100 101
101 102 // radio buttons layout
102 103 QVBoxLayout* radioLayout = new QVBoxLayout;
103 104 radioLayout->addWidget(m_lineRadioButton);
104 105 radioLayout->addWidget(m_splineRadioButton);
105 106 radioLayout->addWidget(m_scatterRadioButton);
106 107 radioLayout->addWidget(m_pieRadioButton);
107 108 radioLayout->addWidget(m_areaRadioButton);
108 109 radioLayout->addWidget(m_barRadioButton);
109 110 radioLayout->addStretch();
110 111
111 112 // create main layout
112 113 QGridLayout* mainLayout = new QGridLayout;
113 114 mainLayout->addLayout(buttonsLayout, 1, 1);
114 115 mainLayout->addLayout(radioLayout, 2, 1);
115 116 mainLayout->addWidget(m_tableView, 1, 0);
116 117 mainLayout->addWidget(m_chartView, 2, 0);
117 118 setLayout(mainLayout);
118 119 m_lineRadioButton->setFocus();
119 120 }
120 121
121 122 void TableWidget::addRowAbove()
122 123 {
123 124 m_model->insertRows(m_tableView->currentIndex().row(), m_linesCountSpinBox->value());
124 125
125 126 }
126 127
127 128 void TableWidget::addRowBelow()
128 129 {
129 130 m_model->insertRows(m_tableView->currentIndex().row() + 1, m_linesCountSpinBox->value());
130 131
131 132 }
132 133
133 134 void TableWidget::removeRow()
134 135 {
135 136 m_model->removeRows(m_tableView->currentIndex().row(), qMin(m_model->rowCount() - m_tableView->currentIndex().row(), m_linesCountSpinBox->value()));
136 137 }
137 138
138 139 void TableWidget::updateChartType(bool toggle)
139 140 {
140 141 // this if is needed, so that the function is only called once.
141 142 // For the radioButton that was enabled.
142 143 if (toggle) {
143 144 m_chart->removeAllSeries();
144 145 m_chart->axisX()->setNiceNumbersEnabled(false);
145 146 m_chart->axisY()->setNiceNumbersEnabled(false);
146 147
147 148 // renable axes of the chart (pie hides them)
148 149 // x axis
149 150 QAxis *axis = m_chart->axisX();
150 151 axis->setAxisVisible(true);
151 152 axis->setGridLineVisible(true);
152 153 axis->setLabelsVisible(true);
153 154
154 155 // y axis
155 156 axis = m_chart->axisY();
156 157 axis->setAxisVisible(true);
157 158 axis->setGridLineVisible(true);
158 159 axis->setLabelsVisible(true);
159 160
160 161 m_model->clearMapping();
161 162
162 163 QString seriesColorHex = "#000000";
163 164 QPen pen;
164 165 pen.setWidth(2);
165 166
166 167 if (m_lineRadioButton->isChecked())
167 168 {
168 169 // series 1
169 170 m_series = new QLineSeries;
170 171 m_series->setModel(m_model);
171 172 m_series->setModelMapping(0,1, Qt::Vertical);
172 // m_series->setModelMappingRange(1, 4);
173 m_series->setModelMappingRange(4, 4);
173 174 m_chart->addSeries(m_series);
174 175 seriesColorHex = "#" + QString::number(m_series->pen().color().rgb(), 16).right(6).toUpper();
175 m_model->addMapping(seriesColorHex, QRect(0, 1, 2, 4));
176 m_model->addMapping(seriesColorHex, QRect(0, 4, 2, 4));
176 177
177 178 // series 2
178 179 m_series = new QLineSeries;
179 180 m_series->setModel(m_model);
180 181 m_series->setModelMapping(2,3, Qt::Vertical);
181 182 m_chart->addSeries(m_series);
182 183 seriesColorHex = "#" + QString::number(m_series->pen().color().rgb(), 16).right(6).toUpper();
183 184 m_model->addMapping(seriesColorHex, QRect(2, 0, 2, 1000));
184 185
185 186 // series 3
186 187 m_series = new QLineSeries;
187 188 m_series->setModel(m_model);
188 189 m_series->setModelMapping(4,5, Qt::Vertical);
189 // m_series->setModelMappingRange(2, 0);
190 m_series->setModelMappingRange(2, -1);
190 191 m_chart->addSeries(m_series);
191 192 seriesColorHex = "#" + QString::number(m_series->pen().color().rgb(), 16).right(6).toUpper();
192 193 m_model->addMapping(seriesColorHex, QRect(4, 2, 2, 1000));
193 194 }
194 195 else if (m_splineRadioButton->isChecked())
195 196 {
196 197 // series 1
197 198 m_series = new QSplineSeries;
198 199 m_series->setModel(m_model);
199 200 m_series->setModelMapping(0,1, Qt::Vertical);
200 201 // m_series->setModelMappingRange(1, 4);
201 202 // series->setModelMapping(0,1, Qt::Horizontal);
202 203 m_chart->addSeries(m_series);
203 204 seriesColorHex = "#" + QString::number(m_series->pen().color().rgb(), 16).right(6).toUpper();
204 205 m_model->addMapping(seriesColorHex, QRect(0, 1, 2, 4));
205 206
206 207 // series 2
207 208 m_series = new QSplineSeries;
208 209 m_series->setModel(m_model);
209 210 m_series->setModelMapping(2,3, Qt::Vertical);
210 211 // m_series->setModelMappingRange(0, 0);
211 212 // series->setModelMapping(2,3, Qt::Horizontal);
212 213 m_chart->addSeries(m_series);
213 214 seriesColorHex = "#" + QString::number(m_series->pen().color().rgb(), 16).right(6).toUpper();
214 215 m_model->addMapping(seriesColorHex, QRect(2, 0, 2, 1000));
215 216
216 217 // series 3
217 218 m_series = new QSplineSeries;
218 219 m_series->setModel(m_model);
219 220 m_series->setModelMapping(4,5, Qt::Vertical);
220 221 // m_series->setModelMappingRange(2, 0);
221 222 // series->setModelMapping(4,5, Qt::Horizontal);
222 223 m_chart->addSeries(m_series);
223 224 seriesColorHex = "#" + QString::number(m_series->pen().color().rgb(), 16).right(6).toUpper();
224 225 m_model->addMapping(seriesColorHex, QRect(4, 2, 2, 1000));
225 226 }
226 227 else if (m_scatterRadioButton->isChecked())
227 228 {
228 229 // series 1
229 230 m_series = new QScatterSeries;
230 231 m_series->setModel(m_model);
231 232 m_series->setModelMapping(0,1, Qt::Vertical);
232 233 // m_series->setModelMappingRange(2, 0);
233 234 // series->setModelMapping(0,1, Qt::Horizontal);
234 235 m_chart->addSeries(m_series);
235 236
236 237 seriesColorHex = "#" + QString::number(m_series->brush().color().rgb(), 16).right(6).toUpper();
237 238 m_model->addMapping(seriesColorHex, QRect(0, 2, 2, 1000));
238 239
239 240 // series 2
240 241 m_series = new QScatterSeries;
241 242 m_series->setModel(m_model);
242 243 m_series->setModelMapping(2,3, Qt::Vertical);
243 244 // m_series->setModelMappingRange(1, 6);
244 245 // series->setModelMapping(2,3, Qt::Horizontal);
245 246 m_chart->addSeries(m_series);
246 247
247 248 seriesColorHex = "#" + QString::number(m_series->brush().color().rgb(), 16).right(6).toUpper();
248 249 m_model->addMapping(seriesColorHex, QRect(2, 1, 2, 6));
249 250
250 251 // series 3
251 252 m_series = new QScatterSeries;
252 253 m_series->setModel(m_model);
253 254 m_series->setModelMapping(4,5, Qt::Vertical);
254 255 // series->setModelMapping(4,5, Qt::Horizontal);
255 256 m_chart->addSeries(m_series);
256 257 seriesColorHex = "#" + QString::number(m_series->brush().color().rgb(), 16).right(6).toUpper();
257 258 m_model->addMapping(seriesColorHex, QRect(4, 0, 2, 1000));
258 259 }
259 260 else if (m_pieRadioButton->isChecked())
260 261 {
261 262 // pie 1
262 263 QPieSeries* pieSeries = new QPieSeries;
263 264 pieSeries->setModel(m_model);
264 265 pieSeries->setModelMapping(0,0, Qt::Vertical);
265 266 pieSeries->setLabelsVisible(true);
266 267 pieSeries->setPieSize(0.4);
267 268 pieSeries->setHorizontalPosition(0.2);
268 269 pieSeries->setVerticalPosition(0.35);
269 270
270 271 m_chart->addSeries(pieSeries);
271 272 seriesColorHex = "#" + QString::number(pieSeries->slices().at(pieSeries->slices().count()/2)->brush().color().rgb(), 16).right(6).toUpper();
272 273 m_model->addMapping(seriesColorHex, QRect(0, 0, 1, 1000));
273 274
274 275 // pie 2
275 276 pieSeries = new QPieSeries;
276 277 pieSeries->setModel(m_model);
277 278 pieSeries->setModelMapping(1,1, Qt::Vertical);
278 279 pieSeries->setLabelsVisible(true);
279 280 pieSeries->setPieSize(0.4);
280 281 pieSeries->setHorizontalPosition(0.8);
281 282 pieSeries->setVerticalPosition(0.35);
282 283 m_chart->addSeries(pieSeries);
283 284 seriesColorHex = "#" + QString::number(pieSeries->slices().at(pieSeries->slices().count()/2)->brush().color().rgb(), 16).right(6).toUpper();
284 285 m_model->addMapping(seriesColorHex, QRect(1, 0, 1, 1000));
285 286
286 287 // pie 3
287 288 pieSeries = new QPieSeries;
288 289 pieSeries->setModel(m_model);
289 290 pieSeries->setModelMapping(2,2, Qt::Vertical);
290 291 pieSeries->setLabelsVisible(true);
291 292 pieSeries->setPieSize(0.4);
292 293 pieSeries->setHorizontalPosition(0.5);
293 294 pieSeries->setVerticalPosition(0.65);
294 295 m_chart->addSeries(pieSeries);
295 296 seriesColorHex = "#" + QString::number(pieSeries->slices().at(pieSeries->slices().count()/2)->brush().color().rgb(), 16).right(6).toUpper();
296 297 m_model->addMapping(seriesColorHex, QRect(2, 0, 1, 1000));
297 298 }
298 299 else if (m_areaRadioButton->isChecked())
299 300 {
300 301 QLineSeries* upperLineSeries = new QLineSeries;
301 302 upperLineSeries->setModel(m_model);
302 303 upperLineSeries->setModelMapping(0, 1, Qt::Vertical);
303 304 // upperLineSeries->setModelMappingRange(1, 5);
304 305 QLineSeries* lowerLineSeries = new QLineSeries;
305 306 lowerLineSeries->setModel(m_model);
306 307 lowerLineSeries->setModelMapping(2, 3, Qt::Vertical);
307 308 QAreaSeries* areaSeries = new QAreaSeries(upperLineSeries, lowerLineSeries);
308 309 m_chart->addSeries(areaSeries);
309 310 seriesColorHex = "#" + QString::number(areaSeries->brush().color().rgb(), 16).right(6).toUpper();
310 311 m_model->addMapping(seriesColorHex, QRect(0, 1, 2, 5));
311 312 m_model->addMapping(seriesColorHex, QRect(2, 0, 2, 1000));
312 313 }
313 314 else if (m_barRadioButton->isChecked())
314 315 {
315 316 QBarSeries* barSeries = new QBarSeries(QStringList());
316 317 barSeries->setModel(m_model);
317 318 barSeries->setModelMapping(5, 2, 4, Qt::Vertical);
318 319 m_chart->addSeries(barSeries);
319 320 QList<QBarSet*> barsets = barSeries->barSets();
320 321 for (int i = 0; i < barsets.count(); i++) {
321 322 seriesColorHex = "#" + QString::number(barsets.at(i)->brush().color().rgb(), 16).right(6).toUpper();
322 323 m_model->addMapping(seriesColorHex, QRect(2 + i, 0, 1, 1000));
323 324 }
324 325 }
325 326
326 327
327 328 if (!m_barRadioButton->isChecked())
328 329 m_chart->axisX()->setRange(0, 500);
329 330 m_chart->axisY()->setRange(0, 120);
330 331 m_chart->legend()->setVisible(true);
331 332
332 333 // repaint table view colors
333 334 m_tableView->repaint();
334 335 m_tableView->setFocus();
335 336 }
336 337 }
337 338
338 339 TableWidget::~TableWidget()
339 340 {
340 341
341 342 }
General Comments 0
You need to be logged in to leave comments. Login now