##// END OF EJS Templates
XYSeries: added support for limited mapping area
Marek Rosa -
r734:cfecc74c9bfa
parent child
Show More
@@ -1,204 +1,214
1 1 #include "customtablemodel.h"
2 2 #include <QVector>
3 #include <QTime>
3 4
4 5 CustomTableModel::CustomTableModel(QObject *parent) :
5 6 QAbstractTableModel(parent)
6 7 {
7 // m_points.append(QPointF(10, 50));
8 // m_labels.append("Apples");
9 // m_points.append(QPointF(60, 70));
10 // m_labels.append("Oranges");
11 // m_points.append(QPointF(110, 50));
12 // m_labels.append("Bananas");
13 // m_points.append(QPointF(140, 40));
14 // m_labels.append("Lemons");
15 // m_points.append(QPointF(200, 150));
16 // m_labels.append("Plums");
17 // m_points.append(QPointF(225, 75));
8 // m_points.append(QPointF(10, 50));
9 // m_labels.append("Apples");
10 // m_points.append(QPointF(60, 70));
11 // m_labels.append("Oranges");
12 // m_points.append(QPointF(110, 50));
13 // m_labels.append("Bananas");
14 // m_points.append(QPointF(140, 40));
15 // m_labels.append("Lemons");
16 // m_points.append(QPointF(200, 150));
17 // m_labels.append("Plums");
18 // m_points.append(QPointF(225, 75));
18 19 // m_labels.append("Pearls");
19 20
21 qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
22
20 23 // m_data
21 24 for (int i = 0; i < 6; i++)
22 25 {
23 26 QVector<qreal>* dataVec = new QVector<qreal>(6);
24 27 for (int k = 0; k < dataVec->size(); k++)
25 28 if (k%2 == 0)
26 29 dataVec->replace(k, i * 50 + qrand()%20);
27 30 else
28 31 dataVec->replace(k, qrand()%100);
29 32 m_data.append(dataVec);
30 33 m_labels.append(QString("Row: %1").arg((i + 1)));
31 34 }
32 35 }
33 36
34 37 int CustomTableModel::rowCount(const QModelIndex & parent) const
35 38 {
36 39 Q_UNUSED(parent)
37 40 // return m_points.count();
38 41 return m_data.count();
39 42 }
40 43
41 44 int CustomTableModel::columnCount(const QModelIndex & parent) const
42 45 {
43 46 Q_UNUSED(parent)
44 47 // return 3;
45 48 return 6;
46 49 }
47 50
48 51 QVariant CustomTableModel::headerData (int section, Qt::Orientation orientation, int role ) const
49 52 {
50 53 if (role != Qt::DisplayRole)
51 54 return QVariant();
52 55
53 56 if (orientation == Qt::Horizontal)
54 57 {
55 58 switch(section)
56 59 {
57 60 // case 0:
58 61 // return "x";
59 62 // case 1:
60 63 // return "y";
61 64 // case 2:
62 65 case 6:
63 66 return "Fruit";
64 67 default:
65 68 if (section%2 == 0)
66 69 return "x";
67 70 else
68 71 return "y";
69 72 // return "What?";
70 73 }
71 74 }
72 75 else
73 76 return QString("%1").arg(section + 1);
74 77 }
75 78
76 79 QVariant CustomTableModel::data(const QModelIndex & index, int role) const
77 80 {
78 81 if (role == Qt::DisplayRole)
79 82 {
80 83 switch(index.column())
81 84 {
82 85 // case 0:
83 86 // return m_points[index.row()].x();
84 87 // case 1:
85 88 // return m_points[index.row()].y();
86 89 // case 2:
87 90 case 6:
88 91 return m_labels[index.row()];
89 92 default:
90 93 return m_data[index.row()]->at(index.column());
91 94 break;
92 95 }
93 96 }
94 97 else if (role == Qt::EditRole)
95 98 {
96 99 switch(index.column())
97 100 {
98 101 // case 0:
99 102 // return m_points[index.row()].x();
100 103 // case 1:
101 104 // return m_points[index.row()].y();
102 105 // case 2:
103 106 case 6:
104 107 return m_labels[index.row()];
105 108 default:
106 109 return m_data[index.row()]->at(index.column());
107 110 break;
108 111 }
109 112 }
110 113 return QVariant();
111 114 }
112 115
113 116 bool CustomTableModel::setData ( const QModelIndex & index, const QVariant & value, int role)
114 117 {
115 118 if (index.isValid() && role == Qt::EditRole)
116 119 {
117 120 switch(index.column())
118 121 {
119 122 // case 0:
120 123 // m_points[index.row()].setX(value.toDouble());
121 124 // break;
122 125 // case 1:
123 126 // m_points[index.row()].setY(value.toDouble());
124 127 // break;
125 128 // case 2:
126 129 case 6:
127 130 m_labels.replace(index.row(), value.toString());
128 131 break;
129 132 default:
130 133 m_data[index.row()]->replace(index.column(), value.toDouble());
131 134 break;
132 135 // return false;
133 136 }
134 137 emit dataChanged(index, index);
135 138 return true;
136 139 }
137 140 return false;
138 141 }
139 142
140 143 Qt::ItemFlags CustomTableModel::flags ( const QModelIndex & index ) const
141 144 {
142 145 // if (!index.isValid())
143 146 // return Qt::ItemIsEnabled;
144 147 return QAbstractItemModel::flags(index) | Qt::ItemIsEditable;
145 148 }
146 149
147 150 bool CustomTableModel::insertRows ( int row, int count, const QModelIndex & parent)
148 151 {
149 152 Q_UNUSED(parent)
150 153
151 154 if (row < 0)
152 155 row = 0;
153 156 beginInsertRows(QModelIndex(), row /*dataTable.count()*/, row + count - 1);
154 157 for (int i = row; i < row + count; i++)
155 158 {
156 159 // m_points.insert(row, QPointF(10,20));
157 160 QVector<qreal>* dataVec = new QVector<qreal>(6);
158 161 for (int k = 0; k < dataVec->size(); k++)
159 162 if (k%2 == 0)
160 163 // dataVec->replace(k, i * 50 + qrand()%20);
161 164 {
162 165 int difference = 0;
163 166 if (row < m_data.size())
164 167 {
165 168 if (row - 1 >= 0)
166 169 {
167 170 difference = (int)(qAbs(m_data[row]->at(k) - m_data[row - 1]->at(k)));
168 171 dataVec->replace(k, m_data[row - 1]->at(k) + qrand()%qMax(1, difference));
169 172 }
170 173 else
171 dataVec->replace(k, qrand()%20);
174 dataVec->replace(k, qrand()%40 + 10);
172 175 }
173 176 else
174 dataVec->replace(k, m_data[row - 1]->at(k) + qrand()%20);
177 if (row - 1 >= 0)
178 {
179 dataVec->replace(k, m_data[row - 1]->at(k) + qrand()%40 + 10);
180 }
181 else
182 {
183 dataVec->replace(k, qrand()%40 + 10);
184 }
175 185 }
176 186 else
177 187 dataVec->replace(k, qrand()%100);
178 188 m_data.insert(row, dataVec);
179 189 m_labels.insert(row,(QString("Row: %1").arg(row + 1)));
180 190 }
181 191 endInsertRows();
182 192 return true;
183 193 }
184 194
185 195 bool CustomTableModel::removeRows ( int row, int count, const QModelIndex & parent)
186 196 {
187 197 if (row > this->rowCount() - 1)
188 198 return false;
189 199 if (row < 0)
190 200 row = 0;
191 201 if (row + count > rowCount())
192 202 return false;
193 203 beginRemoveRows(parent, row, row + count - 1);
194 204 for (int i = row; i < row + count; i++)
195 205 {
196 // m_points.removeAt(row);
206 // m_points.removeAt(row);
197 207 QVector<qreal>* item = m_data.at(row);
198 208 m_data.removeAt(row);
199 209 delete item;
200 210 m_labels.removeAt(row);
201 211 }
202 212 endRemoveRows();
203 213 return true;
204 214 }
@@ -1,249 +1,251
1 1 #include "tablewidget.h"
2 2 #include <QGridLayout>
3 3 #include <QTableView>
4 4 #include <QStyledItemDelegate>
5 5 #include "qlineseries.h"
6 6 #include "qsplineseries.h"
7 7 #include "qscatterseries.h"
8 8 #include "customtablemodel.h"
9 9 #include "qpieseries.h"
10 10 #include "qareaseries.h"
11 11 #include "qbarseries.h"
12 12 #include <QPushButton>
13 13 #include <QRadioButton>
14 14 #include <QTime>
15 15
16 16 TableWidget::TableWidget(QWidget *parent)
17 17 : QWidget(parent)
18 18 {
19 19 setGeometry(100, 100, 1000, 600);
20 20 qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
21 21 // create simple model for storing data
22 22 // user's table data model
23 23 m_model = new CustomTableModel;
24 24 tableView = new QTableView;
25 25 tableView->setModel(m_model);
26 26 tableView->setMinimumHeight(240);
27 27 // tableView->setMinimumSize(340, 480);
28 28 // tableView->setItemDelegate(new QStyledItemDelegate);
29 29 chartView = new QChartView(this);
30 30 chartView->setRenderHint(QPainter::Antialiasing);
31 31 chartView->setMinimumSize(640, 480);
32 32
33 33 // create
34 34 // QLineSeries* series = new QLineSeries;
35 35 // QSplineSeries* series = new QSplineSeries;
36 36 // QScatterSeries* series = new QScatterSeries;
37 37 // series->setModel(m_model);
38 38 // series->setModelMapping(0,1, Qt::Vertical);
39 39
40 40 // QPieSeries* pieSeries = new QPieSeries;
41 41 // pieSeries->setModel(model);
42 42 // pieSeries
43 43
44 44 // chartView->addSeries(series);
45 45
46 46 // add, remove data buttons
47 47 QPushButton* addRowAboveButton = new QPushButton("Add row above");
48 48 connect(addRowAboveButton, SIGNAL(clicked()), this, SLOT(addRowAbove()));
49 49
50 50 QPushButton* addRowBelowButton = new QPushButton("Add row below");
51 51 connect(addRowBelowButton, SIGNAL(clicked()), this, SLOT(addRowBelow()));
52 52
53 53 QPushButton* removeRowButton = new QPushButton("Remove row");
54 54 connect(removeRowButton, SIGNAL(clicked()), this, SLOT(removeRow()));
55 55
56 56 // buttons layout
57 57 QVBoxLayout* buttonsLayout = new QVBoxLayout;
58 58 buttonsLayout->addWidget(addRowAboveButton);
59 59 buttonsLayout->addWidget(addRowBelowButton);
60 60 buttonsLayout->addWidget(removeRowButton);
61 61 buttonsLayout->addStretch();
62 62
63 63 // chart type radio buttons
64 64 lineRadioButton = new QRadioButton("Line");
65 65 splineRadioButton = new QRadioButton("Spline");
66 66 scatterRadioButton = new QRadioButton("Scatter");
67 67 pieRadioButton = new QRadioButton("Pie");
68 68 areaRadioButton = new QRadioButton("Area");
69 69 barRadioButton = new QRadioButton("Bar");
70 70
71 71 connect(lineRadioButton, SIGNAL(toggled(bool)), this, SLOT(updateChartType()));
72 72 connect(splineRadioButton, SIGNAL(toggled(bool)), this, SLOT(updateChartType()));
73 73 connect(scatterRadioButton, SIGNAL(toggled(bool)), this, SLOT(updateChartType()));
74 74 connect(pieRadioButton, SIGNAL(toggled(bool)), this, SLOT(updateChartType()));
75 75 connect(areaRadioButton, SIGNAL(toggled(bool)), this, SLOT(updateChartType()));
76 76 connect(barRadioButton, SIGNAL(toggled(bool)), this, SLOT(updateChartType()));
77 77 lineRadioButton->setChecked(true);
78 78
79 79 // radio buttons layout
80 80 QVBoxLayout* radioLayout = new QVBoxLayout;
81 81 radioLayout->addWidget(lineRadioButton);
82 82 radioLayout->addWidget(splineRadioButton);
83 83 radioLayout->addWidget(scatterRadioButton);
84 84 radioLayout->addWidget(pieRadioButton);
85 85 radioLayout->addWidget(areaRadioButton);
86 86 radioLayout->addWidget(barRadioButton);
87 87 radioLayout->addStretch();
88 88
89 89 // create main layout
90 90 QGridLayout* mainLayout = new QGridLayout;
91 91 mainLayout->addLayout(buttonsLayout, 1, 0);
92 92 mainLayout->addLayout(radioLayout, 2, 0);
93 93 mainLayout->addWidget(tableView, 1, 1);
94 94 mainLayout->addWidget(chartView, 2, 1);
95 95 setLayout(mainLayout);
96 96 lineRadioButton->setFocus();
97 97 }
98 98
99 99 void TableWidget::addRowAbove()
100 100 {
101 101 // m_model->insertRow(m_model->rowCount());
102 102 m_model->insertRow(tableView->currentIndex().row());
103 103
104 104 }
105 105
106 106 void TableWidget::addRowBelow()
107 107 {
108 108 // m_model->insertRow(m_model->rowCount());
109 109 m_model->insertRow(tableView->currentIndex().row() + 1);
110 110
111 111 }
112 112
113 113 void TableWidget::removeRow()
114 114 {
115 115 // m_model->removeRow(m_model->rowCount() - 1);
116 116 m_model->removeRow(tableView->currentIndex().row());
117 117 }
118 118
119 119 void TableWidget::updateChartType()
120 120 {
121 121 chartView->removeAllSeries();
122 122
123 123 if (lineRadioButton->isChecked())
124 124 {
125 125 // series 1
126 126 series = new QLineSeries;
127 127 series->setModel(m_model);
128 128 series->setModelMapping(0,1, Qt::Vertical);
129 series->setModelMappingShift(1, 4);
129 130 // series->setModelMapping(0,1, Qt::Horizontal);
130 131 chartView->addSeries(series);
131 132
132 133 // series 2
133 134 series = new QLineSeries;
134 135 series->setModel(m_model);
135 136 series->setModelMapping(2,3, Qt::Vertical);
136 137 // series->setModelMapping(2,3, Qt::Horizontal);
137 138 chartView->addSeries(series);
138 139
139 // series 3
140 series = new QLineSeries;
141 series->setModel(m_model);
142 series->setModelMapping(4,5, Qt::Vertical);
143 // series->setModelMapping(4,5, Qt::Horizontal);
144 chartView->addSeries(series);
140 // // series 3
141 // series = new QLineSeries;
142 // series->setModel(m_model);
143 // series->setModelMapping(4,5, Qt::Vertical);
144 //// series->setModelMapping(4,5, Qt::Horizontal);
145 // chartView->addSeries(series);
145 146 }
146 147 else if (splineRadioButton->isChecked())
147 148 {
148 149 // series 1
149 150 series = new QSplineSeries;
150 series->setModel(m_model);
151 series->setModelMapping(0,1, Qt::Vertical);
151 series->setModel(m_model);
152 series->setModelMapping(0,1, Qt::Vertical);
153 series->setModelMappingShift(1, 4);
152 154 // series->setModelMapping(0,1, Qt::Horizontal);
153 155 chartView->addSeries(series);
154 156
155 157 // series 2
156 158 series = new QSplineSeries;
157 159 series->setModel(m_model);
158 160 series->setModelMapping(2,3, Qt::Vertical);
159 161 // series->setModelMapping(2,3, Qt::Horizontal);
160 162 chartView->addSeries(series);
161 163
162 164 // series 3
163 165 series = new QSplineSeries;
164 166 series->setModel(m_model);
165 167 series->setModelMapping(4,5, Qt::Vertical);
166 168 // series->setModelMapping(4,5, Qt::Horizontal);
167 169 chartView->addSeries(series);
168 170 }
169 171 else if (scatterRadioButton->isChecked())
170 172 {
171 173 // series 1
172 174 series = new QScatterSeries;
173 175 series->setModel(m_model);
174 176 series->setModelMapping(0,1, Qt::Vertical);
175 177 // series->setModelMapping(0,1, Qt::Horizontal);
176 178 chartView->addSeries(series);
177 179
178 180 // series 2
179 181 series = new QScatterSeries;
180 182 series->setModel(m_model);
181 183 series->setModelMapping(2,3, Qt::Vertical);
182 184 // series->setModelMapping(2,3, Qt::Horizontal);
183 185 chartView->addSeries(series);
184 186
185 187 // series 3
186 188 series = new QScatterSeries;
187 189 series->setModel(m_model);
188 190 series->setModelMapping(4,5, Qt::Vertical);
189 191 // series->setModelMapping(4,5, Qt::Horizontal);
190 192 chartView->addSeries(series);
191 193 }
192 194 else if (pieRadioButton->isChecked())
193 195 {
194 196 // pie 1
195 197 QPieSeries* pieSeries = new QPieSeries;
196 198 pieSeries->setModel(m_model);
197 199 pieSeries->setModelMapping(0,0, Qt::Vertical);
198 200 pieSeries->setLabelsVisible(true);
199 201 pieSeries->setPieSize(0.4);
200 202 pieSeries->setPiePosition(0.2, 0.35);
201 203 chartView->addSeries(pieSeries);
202 204
203 205 // pie 2
204 206 pieSeries = new QPieSeries;
205 207 pieSeries->setModel(m_model);
206 208 pieSeries->setModelMapping(1,1, Qt::Vertical);
207 209 pieSeries->setLabelsVisible(true);
208 210 pieSeries->setPieSize(0.4);
209 211 pieSeries->setPiePosition(0.8, 0.35);
210 212 chartView->addSeries(pieSeries);
211 213
212 214 // pie 3
213 215 pieSeries = new QPieSeries;
214 216 pieSeries->setModel(m_model);
215 217 pieSeries->setModelMapping(2,2, Qt::Vertical);
216 218 pieSeries->setLabelsVisible(true);
217 219 pieSeries->setPieSize(0.4);
218 220 pieSeries->setPiePosition(0.5, 0.65);
219 221 chartView->addSeries(pieSeries);
220 222 }
221 223 else if (areaRadioButton->isChecked())
222 224 {
223 225 QLineSeries* upperLineSeries = new QLineSeries;
224 226 upperLineSeries->setModel(m_model);
225 227 upperLineSeries->setModelMapping(0, 1, Qt::Vertical);
226 228 QLineSeries* lowerLineSeries = new QLineSeries;
227 229 lowerLineSeries->setModel(m_model);
228 230 lowerLineSeries->setModelMapping(2, 3, Qt::Vertical);
229 231 QAreaSeries* areaSeries = new QAreaSeries(upperLineSeries, lowerLineSeries);
230 232 chartView->addSeries(areaSeries);
231 233 }
232 234 else if (barRadioButton->isChecked())
233 235 {
234 236 QBarSeries* barSeries = new QBarSeries(QStringList());
235 237 barSeries->setModel(m_model);
236 238 barSeries->setModelMapping(5, 2, 4, Qt::Vertical);
237 239 barSeries->setToolTipEnabled(true);
238 240 chartView->addSeries(barSeries);
239 241 }
240 242
241 243 // series->setModel(m_model);
242 244 // series->setModelMapping(0,1, Qt::Vertical);
243 245 // chartView->addSeries(series);
244 246 }
245 247
246 248 TableWidget::~TableWidget()
247 249 {
248 250
249 251 }
@@ -1,380 +1,391
1 1 #include <QDebug>
2 2 #include "qbarseries.h"
3 3 #include "qbarset.h"
4 4 #include "barchartmodel_p.h"
5 5
6 6 QTCOMMERCIALCHART_BEGIN_NAMESPACE
7 7
8 8 /*!
9 9 \class QBarSeries
10 10 \brief part of QtCommercial chart API.
11 11
12 12 QBarSeries represents a series of data shown as bars. One QBarSeries can contain multible
13 13 QBarSet data sets. QBarSeries groups the data from sets to categories, which are defined
14 14 by QStringList.
15 15
16 16 \mainclass
17 17
18 18 \sa QBarSet, QStackedBarSeries, QPercentBarSeries
19 19 */
20 20
21 21 /*!
22 22 \fn virtual QSeriesType QBarSeries::type() const
23 23 \brief Returns type of series.
24 24 \sa QSeries, QSeriesType
25 25 */
26 26
27 27 /*!
28 28 \fn void QBarSeries::showToolTip(QPoint pos, QString tip)
29 29 \brief \internal \a pos \a tip
30 30 */
31 31
32 32 /*!
33 33 Constructs empty QBarSeries. Parameter \a categories defines the categories for chart.
34 34 QBarSeries is QObject which is a child of a \a parent.
35 35 */
36 36 QBarSeries::QBarSeries(QBarCategories categories, QObject *parent)
37 37 : QSeries(parent)
38 38 ,mModel(new BarChartModel(categories, this))
39 39 {
40 40 m_model = NULL;
41 41 m_mapCategories = -1;
42 42 m_mapBarBottom = -1;
43 43 m_mapBarTop = -1;
44 m_mapFirst = 0;
45 m_mapCount = 0;
44 46 m_mapOrientation = Qt::Vertical;
45 47 }
46 48
47 49 /*!
48 50 Adds a set of bars to series. Takes ownership of \a set.
49 51 Connects the clicked(QString) and rightClicked(QString) signals
50 52 of \a set to this series
51 53 */
52 54 void QBarSeries::addBarSet(QBarSet *set)
53 55 {
54 56 mModel->addBarSet(set);
55 57 connect(set,SIGNAL(clicked(QString)),this,SLOT(barsetClicked(QString)));
56 58 connect(set,SIGNAL(rightClicked(QString)),this,SLOT(barsetRightClicked(QString)));
57 59 connect(set, SIGNAL(valueChanged()), this, SLOT(barsetChanged()));
58 60 emit updatedBars();
59 61 }
60 62
61 63 /*!
62 64 Removes a set of bars from series. Releases ownership of \a set. Doesnt delete \a set.
63 65 Disconnects the clicked(QString) and rightClicked(QString) signals
64 66 of \a set from this series
65 67 */
66 68 void QBarSeries::removeBarSet(QBarSet *set)
67 69 {
68 70 disconnect(set,SIGNAL(clicked(QString)),this,SLOT(barsetClicked(QString)));
69 71 disconnect(set,SIGNAL(rightClicked(QString)),this,SLOT(barsetRightClicked(QString)));
70 72 mModel->removeBarSet(set);
71 73 emit updatedBars();
72 74 }
73 75
74 76 void QBarSeries::insertBarSet(int i, QBarSet *set)
75 77 {
76 78 mModel->insertBarSet(i, set);
77 79 // emit barsetChanged();
78 80 }
79 81
80 82 void QBarSeries::insertCategory(int i, QString category)
81 83 {
82 84 mModel->insertCategory(i, category);
83 85 }
84 86
85 87 void QBarSeries::removeCategory(int i)
86 88 {
87 89 mModel->removeCategory(i);
88 90 }
89 91
90 92 /*!
91 93 Returns number of sets in series.
92 94 */
93 95 int QBarSeries::barsetCount()
94 96 {
95 97 // if(m_model)
96 98 // return m_mapBarTop - m_mapBarBottom;
97 99 // else
98 100 return mModel->barsetCount();
99 101 }
100 102
101 103 /*!
102 104 Returns number of categories in series
103 105 */
104 106 int QBarSeries::categoryCount()
105 107 {
106 108 return mModel->categoryCount();
107 109 }
108 110
109 111 /*!
110 112 Returns a list of sets in series. Keeps ownership of sets.
111 113 */
112 114 QList<QBarSet*> QBarSeries::barSets()
113 115 {
114 116 return mModel->barSets();
115 117 }
116 118
117 119 /*!
118 120 \internal \a index
119 121 */
120 122 QBarSet* QBarSeries::barsetAt(int index)
121 123 {
122 124 return mModel->setAt(index);
123 125 }
124 126
125 127 /*!
126 128 \internal \a category
127 129 */
128 130 QString QBarSeries::categoryName(int category)
129 131 {
130 132 return mModel->categoryName(category);
131 133 }
132 134
133 135 /*!
134 136 Enables or disables tooltip depending on parameter \a enabled.
135 137 Tooltip shows the name of set, when mouse is hovering on top of bar.
136 138 Calling without parameter \a enabled, enables the tooltip
137 139 */
138 140 void QBarSeries::setToolTipEnabled(bool enabled)
139 141 {
140 142 // TODO: what if we add sets after call to this function? Those sets won't have tooltip enabled.
141 143 if (enabled) {
142 144 for (int i=0; i<mModel->barsetCount(); i++) {
143 145 QBarSet *set = mModel->setAt(i);
144 146 connect(set,SIGNAL(showToolTip(QPoint,QString)),this,SIGNAL(showToolTip(QPoint,QString)));
145 147 }
146 148 } else {
147 149 for (int i=0; i<mModel->barsetCount(); i++) {
148 150 QBarSet *set = mModel->setAt(i);
149 151 disconnect(set,SIGNAL(showToolTip(QPoint,QString)),this,SIGNAL(showToolTip(QPoint,QString)));
150 152 }
151 153 }
152 154 }
153 155
154 156
155 157 /*!
156 158 \internal \a category
157 159 */
158 160 void QBarSeries::barsetClicked(QString category)
159 161 {
160 162 emit clicked(qobject_cast<QBarSet*>(sender()), category);
161 163 }
162 164
163 165 /*!
164 166 \internal \a category
165 167 */
166 168 void QBarSeries::barsetRightClicked(QString category)
167 169 {
168 170 emit rightClicked(qobject_cast<QBarSet*>(sender()), category);
169 171 }
170 172
171 173
172 174 /*!
173 175 \internal
174 176 */
175 177 qreal QBarSeries::min()
176 178 {
177 179 return mModel->min();
178 180 }
179 181
180 182 /*!
181 183 \internal
182 184 */
183 185 qreal QBarSeries::max()
184 186 {
185 187 return mModel->max();
186 188 }
187 189
188 190 /*!
189 191 \internal \a set \a category
190 192 */
191 193 qreal QBarSeries::valueAt(int set, int category)
192 194 {
193 195 return mModel->valueAt(set,category);
194 196 }
195 197
196 198 /*!
197 199 \internal \a set \a category
198 200 */
199 201 qreal QBarSeries::percentageAt(int set, int category)
200 202 {
201 203 return mModel->percentageAt(set,category);
202 204 }
203 205
204 206 /*!
205 207 \internal \a category
206 208 */
207 209 qreal QBarSeries::categorySum(int category)
208 210 {
209 211 return mModel->categorySum(category);
210 212 }
211 213
212 214 /*!
213 215 \internal
214 216 */
215 217 qreal QBarSeries::maxCategorySum()
216 218 {
217 219 return mModel->maxCategorySum();
218 220 }
219 221
220 222 /*!
221 223 \internal
222 224 */
223 225 BarChartModel& QBarSeries::model()
224 226 {
225 227 return *mModel;
226 228 }
227 229
228 230 bool QBarSeries::setModel(QAbstractItemModel* model)
229 231 {
230 232 // disconnect signals from old model
231 233 if(m_model)
232 234 {
233 235 disconnect(m_model, 0, this, 0);
234 236 m_mapCategories = -1;
235 237 m_mapBarBottom = -1;
236 238 m_mapBarTop = -1;
239 m_mapFirst = 0;
240 m_mapCount = 0;
237 241 m_mapOrientation = Qt::Vertical;
238 242 }
239 243
240 244 // set new model
241 245 if(model)
242 246 {
243 247 m_model = model;
244 248 return true;
245 249 }
246 250 else
247 251 {
248 252 m_model = NULL;
249 253 return false;
250 254 }
251 255 }
252 256
253 257 // TODO
254 258 void QBarSeries::setModelMapping(int categories, int bottomBoundry, int topBoundry, Qt::Orientation orientation)
255 259 {
256 260 if (m_model == NULL)
257 261 return;
258 262 m_mapCategories = categories;
259 263 m_mapBarBottom = bottomBoundry;
260 264 m_mapBarTop = topBoundry;
265 m_mapFirst = 1;
261 266 m_mapOrientation = orientation;
262 267
263 268 // connect the signals
264 269 if (m_mapOrientation == Qt::Vertical)
265 270 {
271 m_mapCount = m_model->rowCount();
266 272 connect(m_model,SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(modelUpdated(QModelIndex, QModelIndex)));
267 273 connect(m_model,SIGNAL(rowsInserted(QModelIndex, int, int)), this, SLOT(modelDataAdded(QModelIndex,int,int)));
268 274 connect(m_model, SIGNAL(rowsRemoved(QModelIndex, int, int)), this, SLOT(modelDataRemoved(QModelIndex,int,int)));
269 275 }
270 276 else
271 277 {
278 m_mapCount = m_model->columnCount();
272 279 connect(m_model,SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(modelUpdated(QModelIndex, QModelIndex)));
273 280 connect(m_model,SIGNAL(columnsInserted(QModelIndex, int, int)), this, SLOT(modelDataAdded(QModelIndex,int,int)));
274 281 connect(m_model, SIGNAL(columnsRemoved(QModelIndex, int, int)), this, SLOT(modelDataRemoved(QModelIndex,int,int)));
275 282 }
276 283
277 284
278 285 // create the initial bars
279 286 delete mModel;
280 287 if (m_mapOrientation == Qt::Vertical)
281 288 {
282 289 QStringList categories;
283 for (int k = 0; k < m_model->rowCount(); k++)
290 for (int k = m_mapFirst; k < m_mapFirst + m_mapCount; k++)
284 291 categories << m_model->data(m_model->index(k, m_mapCategories), Qt::DisplayRole).toString();
285 292 mModel = new BarChartModel(categories, this);
286 293
287 294 for (int i = m_mapBarBottom; i <= m_mapBarTop; i++)
288 295 {
289 296 QBarSet* barSet = new QBarSet(QString("Column: %1").arg(i + 1));
290 for(int m = 0; m < m_model->rowCount(); m++)
297 for(int m = m_mapFirst; m < m_mapFirst + m_mapCount; m++)
291 298 *barSet << m_model->data(m_model->index(m, i), Qt::DisplayRole).toDouble();
292 299 addBarSet(barSet);
293 300 }
294 301 }
295 302 else
296 303 {
297 304 QStringList categories;
298 for (int k = 0; k < m_model->columnCount(); k++)
305 for (int k = m_mapFirst; k < m_mapFirst + m_mapCount; k++)
299 306 categories << m_model->data(m_model->index(m_mapCategories, k), Qt::DisplayRole).toString();
300 307 mModel = new BarChartModel(categories, this);
301 308
302 309 for (int i = m_mapBarBottom; i <= m_mapBarTop; i++)
303 310 {
304 311 QBarSet* barSet = new QBarSet(QString("Row: %1").arg(i + 1));
305 for(int m = 0; m < m_model->columnCount(); m++)
312 for(int m = m_mapFirst; m < m_mapFirst + m_mapCount; m++)
306 313 *barSet << m_model->data(m_model->index(i, m), Qt::DisplayRole).toDouble();
307 314 addBarSet(barSet);
308 315 }
309 316 }
310 317 }
311 318
319 void QBarSeries::setModelMappingShift(int first, int count)
320 {
321 m_mapFirst = first;
322 m_mapCount = count;
323 }
324
312 325 void QBarSeries::modelUpdated(QModelIndex topLeft, QModelIndex bottomRight)
313 326 {
314 327 Q_UNUSED(bottomRight)
315 328
316 329 if (m_mapOrientation == Qt::Vertical)
317 330 {
318 if (topLeft.column() >= m_mapBarBottom && topLeft.column() <= m_mapBarTop)
319 barsetAt(topLeft.column() - m_mapBarBottom)->setValue(topLeft.row(), m_model->data(topLeft, Qt::DisplayRole).toDouble());
320 // else if (topLeft.column() == m_mapCategories)
321 // slices().at(topLeft.row())->setLabel(m_model->data(topLeft, Qt::DisplayRole).toString());
331 // model update is relevant to BarSeries if the change was made to the part of the model that was mapped to BarSeries
332 if (topLeft.column() >= m_mapBarBottom && topLeft.column() <= m_mapBarTop && topLeft.row() >= m_mapFirst && topLeft.row() < m_mapFirst + m_mapCount)
333 barsetAt(topLeft.column() - m_mapBarBottom)->setValue(topLeft.row() - m_mapFirst, m_model->data(topLeft, Qt::DisplayRole).toDouble());
322 334 }
323 335 else
324 336 {
325 if (topLeft.row() >= m_mapBarBottom && topLeft.row() <= m_mapBarTop)
326 barsetAt(topLeft.row() - m_mapBarBottom)->setValue(topLeft.column(), m_model->data(topLeft, Qt::DisplayRole).toDouble());
327 // else if (topLeft.row() == m_mapCategories)
328 // slices().at(topLeft.column())->setLabel(m_model->data(topLeft, Qt::DisplayRole).toString());
337 // model update is relevant to BarSeries if the change was made to the part of the model that was mapped to BarSeries
338 if (topLeft.row() >= m_mapBarBottom && topLeft.row() <= m_mapBarTop && topLeft.column() >= m_mapFirst && topLeft.column() < m_mapFirst + m_mapCount)
339 barsetAt(topLeft.row() - m_mapBarBottom)->setValue(topLeft.column() - m_mapFirst, m_model->data(topLeft, Qt::DisplayRole).toDouble());
329 340 }
330 341 }
331 342
332 343 void QBarSeries::modelDataAdded(QModelIndex /*parent*/, int start, int /*end*/)
333 344 {
334 345 if (m_mapOrientation == Qt::Vertical)
335 346 {
336 insertCategory(start, QString("Row: %1").arg(start + 1));
347 insertCategory(start - m_mapFirst, QString("Row: %1").arg(start + 1));
337 348 for (int i = 0; i <= m_mapBarTop - m_mapBarBottom; i++)
338 349 {
339 barsetAt(i)->insertValue(start, m_model->data(m_model->index(start, i), Qt::DisplayRole).toDouble());
350 barsetAt(i)->insertValue(start - m_mapFirst, m_model->data(m_model->index(start, i), Qt::DisplayRole).toDouble());
340 351 }
341 352 }
342 353 else
343 354 {
344 insertCategory(start, QString("Column: %1").arg(start + 1));
355 insertCategory(start - m_mapFirst, QString("Column: %1").arg(start + 1));
345 356 for (int i = 0; i <= m_mapBarTop - m_mapBarBottom; i++)
346 357 {
347 barsetAt(i)->insertValue(start, m_model->data(m_model->index(i, start), Qt::DisplayRole).toDouble());
358 barsetAt(i)->insertValue(start - m_mapFirst, m_model->data(m_model->index(i, start), Qt::DisplayRole).toDouble());
348 359 }
349 360 }
350 361 emit restructuredBar(1);
351 362 }
352 363
353 364 void QBarSeries::modelDataRemoved(QModelIndex /*parent*/, int start, int /*end*/)
354 365 {
355 removeCategory(start);
366 removeCategory(start - m_mapFirst);
356 367 for (int i = 0; i <= m_mapBarTop - m_mapBarBottom; i++)
357 368 {
358 barsetAt(i)->removeValue(start);
369 barsetAt(i)->removeValue(start - m_mapFirst);
359 370 }
360 371 emit restructuredBar(1);
361 372 }
362 373
363 374 void QBarSeries::barsetChanged()
364 375 {
365 376 emit updatedBars();
366 377 }
367 378
368 379 QBarCategories QBarSeries::categories() const
369 380 {
370 381 QBarCategories categories;
371 382 int count = mModel->categoryCount();
372 383 for (int i=1; i<=count; i++) {
373 384 categories.insert(i, mModel->categoryName(i-1));
374 385 }
375 386 return categories;
376 387 }
377 388
378 389 #include "moc_qbarseries.cpp"
379 390
380 391 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,95 +1,98
1 1 #ifndef BARSERIES_H
2 2 #define BARSERIES_H
3 3
4 4 #include <qseries.h>
5 5 #include <QStringList>
6 6
7 7 QTCOMMERCIALCHART_BEGIN_NAMESPACE
8 8
9 9 typedef QStringList QBarCategories;
10 10
11 11 class QBarSet;
12 12 class BarChartModel;
13 13 class BarCategory;
14 14
15 15 // Container for series
16 16 class QTCOMMERCIALCHART_EXPORT QBarSeries : public QSeries
17 17 {
18 18 Q_OBJECT
19 19 public:
20 20 QBarSeries(QStringList categories, QObject* parent=0);
21 21
22 22 virtual QSeriesType type() const { return QSeries::SeriesTypeBar; }
23 23
24 24 void addBarSet(QBarSet *set); // Takes ownership of set
25 25 void removeBarSet(QBarSet *set); // Releases ownership, doesn't delete set
26 26 void insertBarSet(int i, QBarSet *set);
27 27 void insertCategory(int i, QString category);
28 28 void removeCategory(int i);
29 29 int barsetCount();
30 30 int categoryCount();
31 31 QList<QBarSet*> barSets();
32 32 QBarCategories categories() const;
33 33
34 34
35 35 bool setModel(QAbstractItemModel* model);
36 36 QAbstractItemModel* modelExt() {return m_model;}
37 37 void setModelMapping(int categories, int bottomBoundry, int topBoundry, Qt::Orientation orientation = Qt::Vertical);
38 void setModelMappingShift(int first, int count);
38 39
39 40 public:
40 41 // TODO: Functions below this are not part of api and will be moved
41 42 // to private implementation, when we start using it
42 43 // TODO: TO PIMPL --->
43 44 QBarSet* barsetAt(int index);
44 45 QString categoryName(int category);
45 46 qreal min();
46 47 qreal max();
47 48 qreal valueAt(int set, int category);
48 49 qreal percentageAt(int set, int category);
49 50 qreal categorySum(int category);
50 51 qreal maxCategorySum();
51 52 BarChartModel& model();
52 53 // <--- TO PIMPL
53 54
54 55 signals:
55 56 //void changed(int index);
56 57 void clicked(QBarSet* barset, QString category); // Up to user of api, what to do with these signals
57 58 void rightClicked(QBarSet* barset, QString category);
58 59
59 60 //
60 61 void updatedBars();
61 62 void restructuredBar(int);
62 63
63 64 // TODO: internal signals, these to private implementation.
64 65 // TODO: TO PIMPL --->
65 66 void showToolTip(QPoint pos, QString tip);
66 67 // <--- TO PIMPL
67 68
68 69 public Q_SLOTS:
69 70 void setToolTipEnabled(bool enabled=true); // enables tooltips
70 71
71 72 // TODO: TO PIMPL --->
72 73 void barsetClicked(QString category);
73 74 void barsetRightClicked(QString category);
74 75 // <--- TO PIMPL
75 76
76 77 private Q_SLOTS:
77 78 // slots for updating bars when data in model changes
78 79 void modelUpdated(QModelIndex topLeft, QModelIndex bottomRight);
79 80 void modelDataAdded(QModelIndex parent, int start, int end);
80 81 void modelDataRemoved(QModelIndex parent, int start, int end);
81 82 void barsetChanged();
82 83
83 84 protected:
84 85 BarChartModel* mModel;
85 86
86 87 // QAbstractItemModel* m_model;
87 88 int m_mapCategories;
88 89 int m_mapBarBottom;
89 90 int m_mapBarTop;
91 int m_mapFirst;
92 int m_mapCount;
90 93 Qt::Orientation m_mapOrientation;
91 94 };
92 95
93 96 QTCOMMERCIALCHART_END_NAMESPACE
94 97
95 98 #endif // BARSERIES_H
@@ -1,155 +1,161
1 1 #include "qsplineseries.h"
2 2
3 3 /*!
4 4 \class QSplineSeries
5 5 \brief Series type used to store data needed to draw a spline.
6 6
7 7 QSplineSeries stores the data points along with the segment control points needed by QPainterPath to draw spline
8 8 Control points are automatically calculated when data changes. The algorithm computes the points so that the normal spline can be drawn.
9 9 */
10 10
11 11 /*!
12 12 \fn QSeriesType QSplineSeries::type() const
13 13 Returns the type of the series
14 14 */
15 15
16 16 /*!
17 17 \fn QSeriesType QSplineSeries::controlPoint(int index) const
18 18 Returns the control point specified by \a index
19 19 */
20 20
21 21 QTCOMMERCIALCHART_BEGIN_NAMESPACE
22 22
23 23 /*!
24 24 Constructs empty series object which is a child of \a parent.
25 25 When series object is added to QChartView or QChart instance then the ownerships is transfered.
26 26 */
27 27
28 28 QSplineSeries::QSplineSeries(QObject *parent) :
29 29 QLineSeries(parent)
30 30 {
31 31 connect(this,SIGNAL(pointAdded(int)), this, SLOT(updateControlPoints()));
32 32 connect(this,SIGNAL(pointRemoved(int)), this, SLOT(updateControlPoints()));
33 33 connect(this,SIGNAL(pointReplaced(int)), this, SLOT(updateControlPoints()));
34 34 }
35 35
36 36 /*!
37 37 \internal
38 38 Calculates control points which are needed by QPainterPath.cubicTo function to draw the cubic Bezier cureve between two points.
39 39 */
40 40 void QSplineSeries::calculateControlPoints()
41 41 {
42 42
43 43 // Based on http://www.codeproject.com/Articles/31859/Draw-a-Smooth-Curve-through-a-Set-of-2D-Points-wit
44 44 // CPOL License
45 45
46 46 int n = count() - 1;
47 47 if (n == 1)
48 48 { // Special case: Bezier curve should be a straight line.
49 49 // firstControlPoints = new Point[1];
50 50 // 3P1 = 2P0 + P3
51 51 m_controlPoints.append(QPointF((2 * x(0) + x(1)) / 3, (2 * y(0) + y(1)) / 3));
52 52
53 53 // P2 = 2P1 P0
54 54 m_controlPoints.append(QPointF(2 * m_controlPoints[0].x() - x(0), 2 * m_controlPoints[0].y() - y(0)));
55 55 return;
56 56 }
57 57
58 58 // Calculate first Bezier control points
59 59 // Right hand side vector
60 60 // Set of equations for P0 to Pn points.
61 61 //
62 62 // | 2 1 0 0 ... 0 0 0 ... 0 0 0 | | P1_1 | | P0 + 2 * P1 |
63 63 // | 1 4 1 0 ... 0 0 0 ... 0 0 0 | | P1_2 | | 4 * P1 + 2 * P2 |
64 64 // | 0 1 4 1 ... 0 0 0 ... 0 0 0 | | P1_3 | | 4 * P2 + 2 * P3 |
65 65 // | . . . . . . . . . . . . | | ... | | ... |
66 66 // | 0 0 0 0 ... 1 4 1 ... 0 0 0 | * | P1_i | = | 4 * P(i-1) + 2 * Pi |
67 67 // | . . . . . . . . . . . . | | ... | | ... |
68 68 // | 0 0 0 0 0 0 0 0 ... 1 4 1 | | P1_(n-1)| | 4 * P(n-2) + 2 * P(n-1) |
69 69 // | 0 0 0 0 0 0 0 0 ... 0 2 7 | | P1_n | | 8 * P(n-1) + Pn |
70 70 //
71 71 QList<qreal> rhs;
72 72 rhs.append(x(0) + 2 * x(1));
73 73
74 74 // Set right hand side X values
75 75 for (int i = 1; i < n - 1; ++i)
76 76 rhs.append(4 * x(i) + 2 * x(i + 1));
77 77
78 78 rhs.append((8 * x(n - 1) + x(n)) / 2.0);
79 79 // Get first control points X-values
80 80 QList<qreal> xControl = getFirstControlPoints(rhs);
81 81 rhs[0] = y(0) + 2 * y(1);
82 82
83 83 // Set right hand side Y values
84 84 for (int i = 1; i < n - 1; ++i)
85 85 rhs[i] = 4 * y(i) + 2 * y(i + 1);
86 86
87 87 rhs[n - 1] = (8 * y(n - 1) + y(n)) / 2.0;
88 88 // Get first control points Y-values
89 89 QList<qreal> yControl = getFirstControlPoints(rhs);
90 90
91 91 // Fill output arrays.
92 92 for (int i = 0; i < n; ++i)
93 93 {
94 94 // First control point
95 95 m_controlPoints.append(QPointF(xControl[i], yControl[i]));
96 96 // Second control point
97 97 if (i < n - 1)
98 98 m_controlPoints.append(QPointF(2 * x(i + 1) - xControl[i + 1], 2 * y(i + 1) - yControl[i + 1]));
99 99 else
100 100 m_controlPoints.append(QPointF((x(n) + xControl[n - 1]) / 2, (y(n) + yControl[n - 1]) / 2));
101 101 }
102 102 }
103 103
104 104 /*!
105 105 \internal
106 106 */
107 107 QList<qreal> QSplineSeries::getFirstControlPoints(QList<qreal> rhs)
108 108 {
109 109 QList<qreal> x; // Solution vector.
110 110 QList<qreal> tmp; // Temp workspace.
111 111
112 112 qreal b = 2.0;
113 113 x.append(rhs[0] / b);
114 114 tmp.append(0);
115 115 for (int i = 1; i < rhs.size(); i++) // Decomposition and forward substitution.
116 116 {
117 117 tmp.append(1 / b);
118 118 b = (i < rhs.size() - 1 ? 4.0 : 3.5) - tmp[i];
119 119 x.append((rhs[i] - x[i - 1]) / b);
120 120 }
121 121 for (int i = 1; i < rhs.size(); i++)
122 122 x[rhs.size() - i - 1] -= tmp[rhs.size() - i] * x[rhs.size() - i]; // Backsubstitution.
123 123
124 124 return x;
125 125 }
126 126
127 127 /*!
128 128 \internal
129 129 Updates the control points, besed on currently avaiable knots.
130 130 */
131 131 void QSplineSeries::updateControlPoints()
132 132 {
133 133 if(count() > 1)
134 134 {
135 135 m_controlPoints.clear();
136 136 calculateControlPoints();
137 137 }
138 138 }
139 139
140 140 bool QSplineSeries::setModel(QAbstractItemModel* model)
141 141 {
142 142 QXYSeries::setModel(model);
143 143 // calculateControlPoints();
144 144 return true;
145 145 }
146 146
147 147 void QSplineSeries::setModelMapping(int modelX, int modelY, Qt::Orientation orientation)
148 148 {
149 149 QLineSeries::setModelMapping(modelX, modelY, orientation);
150 // calculateControlPoints();
151 }
152
153 void QSplineSeries::setModelMappingShift(int first, int count)
154 {
155 QLineSeries::setModelMappingShift(first, count);
150 156 calculateControlPoints();
151 157 }
152 158
153 159 #include "moc_qsplineseries.cpp"
154 160
155 161 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,46 +1,47
1 1 #ifndef QSPLINESERIES_H
2 2 #define QSPLINESERIES_H
3 3
4 4 #include <qchartglobal.h>
5 5 #include <QtGlobal>
6 6 #include <qlineseries.h>
7 7 #include <QList>
8 8 #include <QPointF>
9 9
10 10 QTCOMMERCIALCHART_BEGIN_NAMESPACE
11 11
12 12 class QTCOMMERCIALCHART_EXPORT QSplineSeries : public QLineSeries
13 13 {
14 14 Q_OBJECT
15 15 public:
16 16
17 17 QSplineSeries(QObject *parent = 0);
18 18 QSeriesType type() const {return QSeries::SeriesTypeSpline;}
19 19
20 20 // int count() const { return m_x.size(); }
21 21 QPointF controlPoint(int index) const {return m_controlPoints[index];}
22 22 bool setModel(QAbstractItemModel* model);
23 23
24 24 void setModelMapping(int modelX, int modelY, Qt::Orientation orientation = Qt::Vertical);
25 void setModelMappingShift(int first, int count);
25 26
26 27 // TODO: allow the user to set custom control points
27 28 // void setCustomControlPoints(QList<QPointsF> controlPoints);
28 29 // bool calculateControlPointsAutomatically();
29 30 // void setCalculateControlPointsAutomatically();
30 31
31 32
32 33 private:
33 34 void calculateControlPoints();
34 35 QList<qreal> getFirstControlPoints(QList<qreal> rhs);
35 36
36 37 private slots:
37 38 void updateControlPoints();
38 39
39 40 private:
40 41 QList<QPointF> m_controlPoints;
41 42
42 43 };
43 44
44 45 QTCOMMERCIALCHART_END_NAMESPACE
45 46
46 47 #endif // QSPLINESERIES_H
@@ -1,361 +1,517
1 1 #include "qxyseries.h"
2 2
3 3 QTCOMMERCIALCHART_BEGIN_NAMESPACE
4 4
5 5 /*!
6 6 \class QXYSeries
7 7 \brief The QXYSeries class is a base class for line, spline and scatter series.
8 8 */
9 9
10 10 /*!
11 11 \fn QPen QXYSeries::pen() const
12 12 \brief Returns pen used to draw points for series.
13 13 \sa setPen()
14 14 */
15 15
16 16 /*!
17 17 \fn QBrush QXYSeries::brush() const
18 18 \brief Returns brush used to draw points for series.
19 19 \sa setBrush()
20 20 */
21 21
22 22 /*!
23 23 \fn void QXYSeries::clicked(const QPointF& point)
24 24 \brief Signal is emitted when user clicks the \a point on chart.
25 25 */
26 26
27 27 /*!
28 28 \fn void QXYSeries::pointReplaced(int index)
29 29 \brief \internal \a index
30 30 */
31 31
32 32 /*!
33 33 \fn void QXYSeries::pointAdded(int index)
34 34 \brief \internal \a index
35 35 */
36 36
37 37 /*!
38 38 \fn void QXYSeries::pointRemoved(int index)
39 39 \brief \internal \a index
40 40 */
41 41
42 42 /*!
43 43 \fn void QXYSeries::updated()
44 44 \brief \internal
45 45 */
46 46
47 47 /*!
48 48 Constructs empty series object which is a child of \a parent.
49 49 When series object is added to QChartView or QChart instance ownerships is transfered.
50 50 */
51 51 QXYSeries::QXYSeries(QObject* parent):QSeries(parent)
52 52 {
53 53 m_mapX = -1;
54 54 m_mapY = -1;
55 m_mapFirst = 0;
56 m_mapCount = 0;
57 m_mapLimited = false;
55 58 m_mapOrientation = Qt::Vertical;
56 59 // m_mapYOrientation = Qt::Vertical;
57 60 }
58 61 /*!
59 62 Destroys the object. Series added to QChartView or QChart instances are owned by those,
60 63 and are deleted when mentioned object are destroyed.
61 64 */
62 65 QXYSeries::~QXYSeries()
63 66 {
64 67 }
65 68
66 69 /*!
67 70 Adds data point \a x \a y to the series. Points are connected with lines on the chart.
68 71 */
69 72 void QXYSeries::add(qreal x,qreal y)
70 73 {
71 74 Q_ASSERT(m_x.size() == m_y.size());
72 75 m_x<<x;
73 76 m_y<<y;
74 77 emit pointAdded(m_x.size()-1);
75 78 }
76 79
77 80 /*!
78 81 This is an overloaded function.
79 82 Adds data \a point to the series. Points are connected with lines on the chart.
80 83 */
81 84 void QXYSeries::add(const QPointF& point)
82 85 {
83 86 add(point.x(),point.y());
84 87 }
85 88
86 89 /*!
87 90 This is an overloaded function.
88 91 Adds list of data \a points to the series. Points are connected with lines on the chart.
89 92 */
90 93 void QXYSeries::add(const QList<QPointF> points)
91 94 {
92 95 foreach(const QPointF& point , points) {
93 96 add(point.x(),point.y());
94 97 }
95 98 }
96 99
97 100 /*!
98 101 Modifies \a y value for given \a x a value.
99 102 */
100 103 void QXYSeries::replace(qreal x,qreal y)
101 104 {
102 105 int index = m_x.indexOf(x);
103 106 m_x[index]=x;
104 107 m_y[index]=y;
105 108 emit pointReplaced(index);
106 109 }
107 110
108 111 /*!
109 112 This is an overloaded function.
110 113 Replaces current y value of for given \a point x value with \a point y value.
111 114 */
112 115 void QXYSeries::replace(const QPointF& point)
113 116 {
114 117 replace(point.x(),point.y());
115 118 }
116 119
117 120 /*!
118 121 Removes first \a x value and related y value.
119 122 */
120 123 void QXYSeries::remove(qreal x)
121 124 {
122 125 int index = m_x.indexOf(x);
123 126
124 127 if(index==-1) return;
125 128
126 129 m_x.remove(index);
127 130 m_y.remove(index);
128 131
129 132 emit pointRemoved(index);
130 133 }
131 134
132 135 /*!
133 136 Removes current \a x and \a y value.
134 137 */
135 138 void QXYSeries::remove(qreal x,qreal y)
136 139 {
137 140 int index =-1;
138 141 do{
139 142 index = m_x.indexOf(x,index+1);
140 143 }while(index !=-1 && m_y.at(index)!=y);
141 144
142 145 if(index==-1) return;
143 146
144 147 m_x.remove(index);
145 148 m_y.remove(index);
146 149 emit pointRemoved(index);
147 150 }
148 151
149 152 /*!
150 153 Removes current \a point x value. Note \a point y value is ignored.
151 154 */
152 155 void QXYSeries::remove(const QPointF& point)
153 156 {
154 157 remove(point.x(),point.y());
155 158 }
156 159
157 160 /*!
158 161 Removes all data points from the series.
159 162 */
160 163 void QXYSeries::removeAll()
161 164 {
162 165 m_x.clear();
163 166 m_y.clear();
164 167 }
165 168
166 169 /*!
167 170 \internal \a pos
168 171 */
169 172 qreal QXYSeries::x(int pos) const
170 173 {
171 174 if (m_model)
172 175 if (m_mapOrientation == Qt::Vertical)
173 176 // consecutive data is read from model's column
174 return m_model->data(m_model->index(pos, m_mapX), Qt::DisplayRole).toDouble();
177 return m_model->data(m_model->index(pos + m_mapFirst, m_mapX), Qt::DisplayRole).toDouble();
175 178 else
176 179 // consecutive data is read from model's row
177 return m_model->data(m_model->index(m_mapX, pos), Qt::DisplayRole).toDouble();
180 return m_model->data(m_model->index(m_mapX, pos + m_mapFirst), Qt::DisplayRole).toDouble();
178 181 else
179 182 // model is not specified, return the data from series' internal data store
180 183 return m_x.at(pos);
181 184 }
182 185
183 186 /*!
184 187 \internal \a pos
185 188 */
186 189 qreal QXYSeries::y(int pos) const
187 190 {
188 191 if (m_model)
189 192 if (m_mapOrientation == Qt::Vertical)
190 193 // consecutive data is read from model's column
191 return m_model->data(m_model->index(pos, m_mapY), Qt::DisplayRole).toDouble();
194 return m_model->data(m_model->index(pos + m_mapFirst, m_mapY), Qt::DisplayRole).toDouble();
192 195 else
193 196 // consecutive data is read from model's row
194 return m_model->data(m_model->index(m_mapY, pos), Qt::DisplayRole).toDouble();
197 return m_model->data(m_model->index(m_mapY, pos + m_mapFirst), Qt::DisplayRole).toDouble();
195 198 else
196 199 // model is not specified, return the data from series' internal data store
197 200 return m_y.at(pos);
198 201 }
199 202
200 203 /*!
201 204 Returns number of data points within series.
202 205 */
203 206 int QXYSeries::count() const
204 207 {
205 208 Q_ASSERT(m_x.size() == m_y.size());
206 209
207 210 if (m_model) {
208 211 if (m_mapOrientation == Qt::Vertical)
209 // data is in a column, so return the number of items in single column
210 return m_model->rowCount();
212 {
213 // data is in a column. Return the number of mapped items if the model's column have enough items
214 // or the number of items that can be mapped
215 if (m_mapLimited)
216 return qMin(m_mapCount, qMax(m_model->rowCount() - m_mapFirst, 0));
217 else
218 return qMax(m_model->rowCount() - m_mapFirst, 0);
219 }
211 220 else
212 // data is in a row, so return the number of items in single row
213 return m_model->columnCount();
221 {
222 // data is in a row. Return the number of mapped items if the model's row have enough items
223 // or the number of items that can be mapped
224 if (m_mapLimited)
225 return qMin(m_mapCount, qMax(m_model->columnCount() - m_mapFirst, 0));
226 else
227 return qMax(m_model->columnCount() - m_mapFirst, 0);
228 }
214 229 }
215 230
216 231 // model is not specified, return the number of points in the series internal data store
217 232 return m_x.size();
218 233 }
219 234
220 235 /*!
221 236 Returns the data points of the series.
222 237 */
223 238 QList<QPointF> QXYSeries::data()
224 239 {
225 240 QList<QPointF> data;
226 241 for (int i(0); i < m_x.count() && i < m_y.count(); i++)
227 242 data.append(QPointF(m_x.at(i), m_y.at(i)));
228 243 return data;
229 244 }
230 245
231 246
232 247 /*!
233 248 Sets \a pen used for drawing points on the chart. If the pen is not defined, the
234 249 pen from chart theme is used.
235 250 \sa QChart::setChartTheme()
236 251 */
237 252 void QXYSeries::setPen(const QPen& pen)
238 253 {
239 254 if(pen!=m_pen){
240 255 m_pen=pen;
241 256 emit updated();
242 257 }
243 258 }
244 259
245 260 /*!
246 261 Sets \a brush used for drawing points on the chart. If the brush is not defined, brush
247 262 from chart theme setting is used.
248 263 \sa QChart::setChartTheme()
249 264 */
250 265
251 266 void QXYSeries::setBrush(const QBrush& brush)
252 267 {
253 268 if(brush!=m_brush){
254 269 m_brush=brush;
255 270 emit updated();
256 271 }
257 272 }
258 273
259 274
260 275 /*!
261 276 Stream operator for adding a data \a point to the series.
262 277 \sa add()
263 278 */
264 279
265 280 QXYSeries& QXYSeries::operator<< (const QPointF &point)
266 281 {
267 282 add(point);
268 283 return *this;
269 284 }
270 285
271 286
272 287 /*!
273 288 Stream operator for adding a list of \a points to the series.
274 289 \sa add()
275 290 */
276 291
277 292 QXYSeries& QXYSeries::operator<< (const QList<QPointF> points)
278 293 {
279 294 add(points);
280 295 return *this;
281 296 }
282 297
283 298
284 299 void QXYSeries::modelUpdated(QModelIndex topLeft, QModelIndex bottomRight)
285 300 {
286 301 Q_UNUSED(bottomRight)
287 302
288 303 if (m_mapOrientation == Qt::Vertical)
289 emit pointReplaced(topLeft.row());
304 {
305 if (topLeft.row() >= m_mapFirst && (!m_mapLimited || topLeft.row() < m_mapFirst + m_mapCount))
306 emit pointReplaced(topLeft.row() - m_mapFirst);
307 }
308 else
309 {
310 if (topLeft.column() >= m_mapFirst && (!m_mapLimited || topLeft.column() < m_mapFirst + m_mapCount))
311 emit pointReplaced(topLeft.column() - m_mapFirst);
312 }
313 }
314
315 void QXYSeries::modelDataAboutToBeAdded(QModelIndex parent, int start, int end)
316 {
317 Q_UNUSED(parent)
318 // Q_UNUSED(end)
319
320 if (m_mapLimited)
321 {
322 if (start >= m_mapFirst + m_mapCount)
323 // the added data is below mapped area
324 // therefore it has no relevance
325 return;
326 else
327 {
328 // the added data is in the mapped area or before it and update is needed
329
330 // check how many mapped items there is currently (before new items are added)
331 // if the number of items currently is equal the m_mapCount then some needs to be removed from xychartitem
332 // internal storage before new ones can be added
333 if (m_mapCount == count())
334 for (int i = 0; i < qMin(count(), end - start + 1); i++)
335 emit pointRemoved(count() - 1 - i);
336 }
337 }
290 338 else
291 emit pointReplaced(topLeft.column());
339 {
340 // map is not limited (it includes all the items starting from m_mapFirst till the end of model)
341 // nothing to do
342 // emit pointAdded(qMax(start - m_mapFirst, 0));
343 }
292 344 }
293 345
294 346 void QXYSeries::modelDataAdded(QModelIndex parent, int start, int end)
295 347 {
296 348 Q_UNUSED(parent)
297 Q_UNUSED(end)
298 emit pointAdded(start);
349 // Q_UNUSED(end)
350
351 if (m_mapLimited)
352 {
353 if (start >= m_mapFirst + m_mapCount)
354 // the added data is below mapped area
355 // therefore it has no relevance
356 return;
357 else
358 {
359 // the added data is in the mapped area or before it
360 // update needed
361 if (count() > 0)
362 for (int i = 0; i < qMin(m_mapCount, end - start + 1); i++)
363 emit pointAdded(qMax(start + i - m_mapFirst, 0));
364 }
365 }
366 else
367 {
368 // map is not limited (it included all the items starting from m_mapFirst till the end of model)
369 for (int i = 0; i < end - start + 1; i++)
370 emit pointAdded(qMax(start + i - m_mapFirst, 0));
371 }
372 }
373
374 void QXYSeries::modelDataAboutToBeRemoved(QModelIndex parent, int start, int end)
375 {
376 Q_UNUSED(parent)
377 // Q_UNUSED(end)
378
379 if (m_mapLimited)
380 {
381 if (start >= m_mapFirst + m_mapCount)
382 // the removed data is below mapped area
383 // therefore it has no relevance
384 return;
385 else
386 {
387 // the removed data is in the mapped area or before it
388 // update needed
389 int itemsToRemove = qMin(count(), end - start + 1);
390 tempItemsRemoved = itemsToRemove;
391 int z = count();
392 z = z;
393 // if (itemsToRemove > 0)
394 // {
395 for (int i = 0; i < itemsToRemove; i++)
396 emit pointRemoved(qMax(start - m_mapFirst, 0));
397 }
398 }
399 else
400 {
401 // map is not limited (it included all the items starting from m_mapFirst till the end of model)
402 for (int i = 0; i < end - start + 1; i++)
403 emit pointRemoved(qMax(start - m_mapFirst, 0));
404 }
299 405 }
300 406
301 407 void QXYSeries::modelDataRemoved(QModelIndex parent, int start, int end)
302 408 {
303 409 Q_UNUSED(parent)
304 410 Q_UNUSED(end)
305 emit pointRemoved(start);
411
412 // how many items there were before data was removed
413 // int oldCount = count() - 1;
414
415 if (m_mapLimited)
416 {
417 if (start >= m_mapFirst + m_mapCount)
418 // the removed data is below mapped area
419 // therefore it has no relevance
420 return;
421 else
422 {
423 // if there are excess items available (below the map) use them to repopulate mapped area
424 int extraItemsAvailable = 0;
425 if (m_mapOrientation == Qt::Vertical)
426 {
427 extraItemsAvailable = qMax(m_model->rowCount() - m_mapFirst, 0);
428 }
429 else
430 {
431 extraItemsAvailable = qMax(m_model->columnCount() - m_mapFirst, 0);
432 }
433
434 // int extraItemsNeeded = qMin(extraItemsAvailable, tempItemsRemoved);
435 for (int k = 0; k < tempItemsRemoved; k++)
436 if (start - m_mapFirst + k < extraItemsAvailable)
437 {
438 emit pointAdded(count() - m_mapFirst + k);
439 }
440 }
441 }
442 else
443 {
444 // emit pointRemoved(qMax(start - m_mapFirst, 0));
445 }
306 446 }
307 447
308 448 bool QXYSeries::setModel(QAbstractItemModel* model) {
309 449
310 450 // disconnect signals from old model
311 451 if(m_model)
312 452 {
313 453 disconnect(m_model, 0, this, 0);
314 454 m_mapX = -1;
315 455 m_mapY = -1;
456 m_mapFirst = 0;
457 m_mapCount = 0;
458 m_mapLimited = false;
316 459 m_mapOrientation = Qt::Vertical;
317 460 }
318 461
319 462 // set new model
320 463 if(model)
321 464 {
322 465 m_model = model;
323 466 return true;
324 467 }
325 468 else
326 469 {
327 470 m_model = NULL;
328 471 return false;
329 472 }
330 473 }
331 474
332 475 void QXYSeries::setModelMapping(int modelX, int modelY, Qt::Orientation orientation)
333 476 {
334 477 if (m_model == NULL)
335 478 return;
336 479 m_mapX = modelX;
337 480 m_mapY = modelY;
481 m_mapFirst = 0;
338 482 m_mapOrientation = orientation;
339 483 if (m_mapOrientation == Qt::Vertical)
340 484 {
485 // m_mapCount = m_model->rowCount();
341 486 connect(m_model,SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(modelUpdated(QModelIndex, QModelIndex)));
487 connect(m_model,SIGNAL(rowsAboutToBeInserted(QModelIndex, int, int)), this, SLOT(modelDataAboutToBeAdded(QModelIndex,int,int)));
342 488 connect(m_model,SIGNAL(rowsInserted(QModelIndex, int, int)), this, SLOT(modelDataAdded(QModelIndex,int,int)));
489 connect(m_model, SIGNAL(rowsAboutToBeRemoved(QModelIndex, int, int)), this, SLOT(modelDataAboutToBeRemoved(QModelIndex,int,int)));
343 490 connect(m_model, SIGNAL(rowsRemoved(QModelIndex, int, int)), this, SLOT(modelDataRemoved(QModelIndex,int,int)));
344 491 }
345 492 else
346 493 {
494 // m_mapCount = m_model->columnCount();
347 495 connect(m_model,SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(modelUpdated(QModelIndex, QModelIndex)));
496 connect(m_model,SIGNAL(columnsAboutToBeInserted(QModelIndex, int, int)), this, SLOT(modelDataAboutToBeAdded(QModelIndex,int,int)));
348 497 connect(m_model,SIGNAL(columnsInserted(QModelIndex, int, int)), this, SLOT(modelDataAdded(QModelIndex,int,int)));
498 connect(m_model, SIGNAL(columnsAboutToBeRemoved(QModelIndex, int, int)), this, SLOT(modelDataAboutToBeRemoved(QModelIndex,int,int)));
349 499 connect(m_model, SIGNAL(columnsRemoved(QModelIndex, int, int)), this, SLOT(modelDataRemoved(QModelIndex,int,int)));
350 500 }
351 501 }
352 502
353 //void QXYSeries::setModelMappingY(int modelLineIndex, Qt::Orientation orientation)
354 //{
355 // m_mapY = modelLineIndex;
356 // m_mapYOrientation = orientation;
357 //}
503 void QXYSeries::setModelMappingShift(int first, int count)
504 {
505 m_mapFirst = first;
506 if (count == 0)
507 m_mapLimited = false;
508 else
509 {
510 m_mapCount = count;
511 m_mapLimited = true;
512 }
513 }
358 514
359 515 #include "moc_qxyseries.cpp"
360 516
361 517 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,77 +1,81
1 1 #ifndef QXYSERIES_H_
2 2 #define QXYSERIES_H_
3 3
4 4 #include <qchartglobal.h>
5 5 #include <qseries.h>
6 6 #include <QDebug>
7 7 #include <QPen>
8 8 #include <QBrush>
9 9
10 10 QTCOMMERCIALCHART_BEGIN_NAMESPACE
11 11
12 12 class QTCOMMERCIALCHART_EXPORT QXYSeries : public QSeries
13 13 {
14 14 Q_OBJECT
15 15 protected:
16 16 QXYSeries(QObject* parent=0);
17 17 virtual ~QXYSeries();
18 18
19 19 public:
20 20 void add(qreal x, qreal y);
21 21 void add(const QPointF& point);
22 22 void add(const QList<QPointF> points);
23 23 void replace(qreal x,qreal y);
24 24 void replace(const QPointF& point);
25 25 void remove(qreal x);
26 26 void remove(qreal x, qreal y);
27 27 void remove(const QPointF& point);
28 28 void removeAll();
29 29
30 30 int count() const;
31 31 qreal x(int pos) const;
32 32 qreal y(int pos) const;
33 33 QList<QPointF> data();
34 34
35 35 QXYSeries& operator << (const QPointF &point);
36 36 QXYSeries& operator << (const QList<QPointF> points);
37 37
38 38 void setPen(const QPen& pen);
39 39 QPen pen() const {return m_pen;}
40 40 void setBrush(const QBrush& pen);
41 41 QBrush brush() const {return m_brush;}
42 42
43 43 bool setModel(QAbstractItemModel* model);
44 44 QAbstractItemModel* model() {return m_model;}
45 45
46 46 virtual void setModelMapping(int modelX, int modelY, Qt::Orientation orientation = Qt::Vertical);
47 // void setModelMappingY(int modelLineIndex, Qt::Orientation orientation = Qt::Vertical);
47 virtual void setModelMappingShift(int first, int count = 0);
48 48
49 49 private slots:
50 50 void modelUpdated(QModelIndex topLeft, QModelIndex bottomRight);
51 void modelDataAboutToBeAdded(QModelIndex parent, int start, int end);
51 52 void modelDataAdded(QModelIndex parent, int start, int end);
53 void modelDataAboutToBeRemoved(QModelIndex parent, int start, int end);
52 54 void modelDataRemoved(QModelIndex parent, int start, int end);
53 55
54 56 signals:
55 57 void clicked(const QPointF& point);
56 58 void updated();
57 59 void pointReplaced(int index);
58 60 void pointRemoved(int index);
59 61 void pointAdded(int index);
60 62
61 63 protected:
62 64 QVector<qreal> m_x;
63 65 QVector<qreal> m_y;
64 66
65 67 QPen m_pen;
66 68 QBrush m_brush;
67 69
68 // QAbstractItemModel* m_model;
69 int m_mapX;
70 Qt::Orientation m_mapOrientation;
70 int m_mapX;
71 71 int m_mapY;
72 // Qt::Orientation m_mapYOrientation;
72 int m_mapFirst;
73 int m_mapCount;
74 bool m_mapLimited;
75 Qt::Orientation m_mapOrientation;
76 int tempItemsRemoved;
73 77 };
74 78
75 79 QTCOMMERCIALCHART_END_NAMESPACE
76 80
77 81 #endif
General Comments 0
You need to be logged in to leave comments. Login now