##// END OF EJS Templates
Axis refactoring to support better barcharts
Michal Klocek -
r502:c37a1568cc38
parent child
Show More
@@ -50,7 +50,7 int main(int argc, char *argv[])
50 axisX->setLabelsAngle(45);
50 axisX->setLabelsAngle(45);
51 axisX->setGridPen(Qt::DashLine);
51 axisX->setGridPen(Qt::DashLine);
52
52
53 QChartAxisCategories *categoriesX = axisX->categories();
53 QChartAxisCategories* categoriesX = axisX->categories();
54 categoriesX->insert(0,"low");
54 categoriesX->insert(0,"low");
55 categoriesX->insert(50,"medium");
55 categoriesX->insert(50,"medium");
56 categoriesX->insert(100,"High");
56 categoriesX->insert(100,"High");
@@ -62,7 +62,7 int main(int argc, char *argv[])
62 axisY->setLabelsAngle(45);
62 axisY->setLabelsAngle(45);
63 axisY->setShadesBrush(Qt::yellow);
63 axisY->setShadesBrush(Qt::yellow);
64
64
65 QChartAxisCategories *categoriesY = axisY->categories();
65 QChartAxisCategories* categoriesY = axisY->categories();
66 categoriesY->insert(0,"low");
66 categoriesY->insert(0,"low");
67 categoriesY->insert(50,"medium");
67 categoriesY->insert(50,"medium");
68 categoriesY->insert(100,"High");
68 categoriesY->insert(100,"High");
@@ -17,11 +17,9 AxisAnimationItem::~AxisAnimationItem()
17 {
17 {
18 }
18 }
19
19
20 void AxisAnimationItem::updateItem()
20 void AxisAnimationItem::updateLayout(QVector<qreal>& newLayout)
21 {
21 {
22 QVector<qreal> oldLayout = layout();
22 QVector<qreal> oldLayout = layout();
23 AxisItem::updateItem();
24 QVector<qreal> newLayout = layout();
25
23
26 if(newLayout.count()==0) return;
24 if(newLayout.count()==0) return;
27 oldLayout.resize(newLayout.size());
25 oldLayout.resize(newLayout.size());
@@ -21,7 +21,8 public:
21 void setLabelsAngle(int angle);
21 void setLabelsAngle(int angle);
22
22
23 protected:
23 protected:
24 virtual void updateItem();
24 virtual void updateLayout(QVector<qreal>& layout);
25
25 private:
26 private:
26 AxisAnimator *m_animation;
27 AxisAnimator *m_animation;
27 };
28 };
@@ -16,7 +16,10 m_labelsAngle(0),
16 m_grid(parent),
16 m_grid(parent),
17 m_shades(parent),
17 m_shades(parent),
18 m_labels(parent),
18 m_labels(parent),
19 m_axis(parent)
19 m_axis(parent),
20 m_min(0),
21 m_max(0),
22 m_ticksCount(0)
20 {
23 {
21 //initial initialization
24 //initial initialization
22 m_axis.setZValue(ChartPresenter::AxisZValue);
25 m_axis.setZValue(ChartPresenter::AxisZValue);
@@ -26,6 +29,8 m_axis(parent)
26
29
27 QObject::connect(m_chartAxis,SIGNAL(updated()),this,SLOT(handleAxisUpdated()));
30 QObject::connect(m_chartAxis,SIGNAL(updated()),this,SLOT(handleAxisUpdated()));
28 QObject::connect(m_chartAxis->categories(),SIGNAL(updated()),this,SLOT(handleAxisCategoriesUpdated()));
31 QObject::connect(m_chartAxis->categories(),SIGNAL(updated()),this,SLOT(handleAxisCategoriesUpdated()));
32
33 handleAxisUpdated();
29 }
34 }
30
35
31 AxisItem::~AxisItem()
36 AxisItem::~AxisItem()
@@ -49,7 +54,7 void AxisItem::createItems(int count)
49 }
54 }
50 }
55 }
51
56
52 void AxisItem::clear(int count)
57 void AxisItem::deleteItems(int count)
53 {
58 {
54 QList<QGraphicsItem *> lines = m_grid.childItems();
59 QList<QGraphicsItem *> lines = m_grid.childItems();
55 QList<QGraphicsItem *> labels = m_labels.childItems();
60 QList<QGraphicsItem *> labels = m_labels.childItems();
@@ -64,46 +69,22 void AxisItem::clear(int count)
64 }
69 }
65 }
70 }
66
71
67 void AxisItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
72 void AxisItem::updateLayout(QVector<qreal>& layout)
68 {
73 {
69 Q_UNUSED(painter);
70 Q_UNUSED(option);
71 Q_UNUSED(widget);
72 }
73
74 void AxisItem::updateItem()
75 {
76 QStringList labels = createLabels(m_ticks,m_min,m_max);
77
78 int diff = m_thicksList.size() - labels.size();
79
80 if(diff>0) {
81 clear(diff);
82 }
83 else if(diff<0) {
84 createItems(-diff);
85 }
86
87 if(diff!=0) handleAxisUpdated();
88
89 m_thicksList=labels;
90
91 QVector<qreal> layout = calculateLayout();
92 if(layout.count()==0) return;
93 setLayout(layout);
74 setLayout(layout);
94
95 }
75 }
96
76
97 QStringList AxisItem::createLabels(int ticks, qreal min, qreal max)
77 QStringList AxisItem::createLabels(int ticks, qreal min, qreal max) const
98 {
78 {
99 Q_ASSERT(max>=min);
79 Q_ASSERT(max>=min);
80 Q_ASSERT(ticks>0);
100
81
101 QStringList labels;
82 QStringList labels;
102
83
103 QChartAxisCategories* categories = m_chartAxis->categories();
84 QChartAxisCategories* categories = m_chartAxis->categories();
104
85
105 for(int i=0; i<= ticks; i++) {
86 for(int i=0; i< ticks; i++) {
106 qreal value = min + (i * (max - min)/ ticks);
87 qreal value = min + (i * (max - min)/ (ticks-1));
107 if(categories->count()==0) {
88 if(categories->count()==0) {
108 labels << QString::number(value);
89 labels << QString::number(value);
109 }
90 }
@@ -112,6 +93,8 QStringList AxisItem::createLabels(int ticks, qreal min, qreal max)
112 labels << label;
93 labels << label;
113 }
94 }
114 }
95 }
96
97
115 return labels;
98 return labels;
116 }
99 }
117
100
@@ -216,15 +199,17 void AxisItem::setGridPen(const QPen& pen)
216
199
217 QVector<qreal> AxisItem::calculateLayout() const
200 QVector<qreal> AxisItem::calculateLayout() const
218 {
201 {
202 Q_ASSERT(m_ticksCount>=2);
203
219 QVector<qreal> points;
204 QVector<qreal> points;
220 points.resize(m_thicksList.size());
205 points.resize(m_ticksCount);
221
206
222 switch (m_type)
207 switch (m_type)
223 {
208 {
224 case X_AXIS:
209 case X_AXIS:
225 {
210 {
226 const qreal deltaX = m_rect.width()/(m_thicksList.size()-1);
211 const qreal deltaX = m_rect.width()/(m_ticksCount-1);
227 for (int i = 0; i < m_thicksList.size(); ++i) {
212 for (int i = 0; i < m_ticksCount; ++i) {
228 int x = i * deltaX + m_rect.left();
213 int x = i * deltaX + m_rect.left();
229 points[i] = x;
214 points[i] = x;
230 }
215 }
@@ -232,8 +217,8 QVector<qreal> AxisItem::calculateLayout() const
232 break;
217 break;
233 case Y_AXIS:
218 case Y_AXIS:
234 {
219 {
235 const qreal deltaY = m_rect.height()/(m_thicksList.size()-1);
220 const qreal deltaY = m_rect.height()/(m_ticksCount-1);
236 for (int i = 0; i < m_thicksList.size(); ++i) {
221 for (int i = 0; i < m_ticksCount; ++i) {
237 int y = i * -deltaY + m_rect.bottom();
222 int y = i * -deltaY + m_rect.bottom();
238 points[i] = y;
223 points[i] = y;
239 }
224 }
@@ -243,77 +228,93 QVector<qreal> AxisItem::calculateLayout() const
243 return points;
228 return points;
244 }
229 }
245
230
246 void AxisItem::setLayout(const QVector<qreal>& layout)
231 void AxisItem::setLayout(QVector<qreal>& layout)
247 {
232 {
233 int diff = m_layoutVector.size() - layout.size();
234
235 if(diff>0) {
236 deleteItems(diff);
237 }
238 else if(diff<0) {
239 createItems(-diff);
240 }
241
242 QList<QGraphicsItem *> lines = m_grid.childItems();
243 QList<QGraphicsItem *> labels = m_labels.childItems();
244 QList<QGraphicsItem *> shades = m_shades.childItems();
245 QList<QGraphicsItem *> axis = m_axis.childItems();
246
247 Q_ASSERT(labels.size() == m_ticksList.size());
248 Q_ASSERT(layout.size() == m_ticksList.size());
249
250 switch (m_type)
251 {
252 case X_AXIS:
253 {
254 QGraphicsLineItem *lineItem = static_cast<QGraphicsLineItem*>(axis.at(0));
255 lineItem->setLine(m_rect.left(), m_rect.bottom(), m_rect.right(), m_rect.bottom());
256
257 for (int i = 0; i < layout.size(); ++i) {
258 QGraphicsLineItem *lineItem = static_cast<QGraphicsLineItem*>(lines.at(i));
259 lineItem->setLine(layout[i], m_rect.top(), layout[i], m_rect.bottom());
260 QGraphicsSimpleTextItem *labelItem = static_cast<QGraphicsSimpleTextItem*>(labels.at(i));
261 labelItem->setText(m_ticksList.at(i));
262 QPointF center = labelItem->boundingRect().center();
263 labelItem->setTransformOriginPoint(center.x(), center.y());
264 labelItem->setPos(layout[i] - center.x(), m_rect.bottom() + label_padding);
265 if(i%2 && i+1 < layout.size()) {
266 QGraphicsRectItem *rectItem = static_cast<QGraphicsRectItem*>(shades.at(i/2));
267 rectItem->setRect(layout[i],m_rect.top(),layout[i+1]-layout[i],m_rect.height());
268 }
269 lineItem = static_cast<QGraphicsLineItem*>(axis.at(i+1));
270 lineItem->setLine(layout[i],m_rect.bottom(),layout[i],m_rect.bottom()+5);
271 }
272 }
273 break;
274
275 case Y_AXIS:
276 {
277 QGraphicsLineItem *lineItem = static_cast<QGraphicsLineItem*>(axis.at(0));
278 lineItem->setLine(m_rect.left() , m_rect.top(), m_rect.left(), m_rect.bottom());
279
280 for (int i = 0; i < layout.size(); ++i) {
281 QGraphicsLineItem *lineItem = static_cast<QGraphicsLineItem*>(lines.at(i));
282 lineItem->setLine(m_rect.left() , layout[i], m_rect.right(), layout[i]);
283 QGraphicsSimpleTextItem *labelItem = static_cast<QGraphicsSimpleTextItem*>(labels.at(i));
284 labelItem->setText(m_ticksList.at(i));
285 QPointF center = labelItem->boundingRect().center();
286 labelItem->setTransformOriginPoint(center.x(), center.y());
287 labelItem->setPos(m_rect.left() - labelItem->boundingRect().width() - label_padding , layout[i]-center.y());
288 if(i%2 && i+1 < layout.size()) {
289 QGraphicsRectItem *rectItem = static_cast<QGraphicsRectItem*>(shades.at(i/2));
290 rectItem->setRect(m_rect.left(),layout[i],m_rect.width(),layout[i]-layout[i+1]);
291 }
292 lineItem = static_cast<QGraphicsLineItem*>(axis.at(i+1));
293 lineItem->setLine(m_rect.left()-5,layout[i],m_rect.left(),layout[i]);
294 }
295 }
296 break;
297 default:
298 qDebug()<<"Unknown axis type";
299 break;
300 }
301
302 if(diff!=0) handleAxisUpdated();
303 m_layoutVector=layout;
304 }
248
305
249 QList<QGraphicsItem *> lines = m_grid.childItems();
306 bool AxisItem::isEmpty()
250 QList<QGraphicsItem *> labels = m_labels.childItems();
307 {
251 QList<QGraphicsItem *> shades = m_shades.childItems();
308 return m_rect.isEmpty() || m_min==m_max || m_ticksCount==0;
252 QList<QGraphicsItem *> axis = m_axis.childItems();
253
254 Q_ASSERT(labels.size() == m_thicksList.size());
255 Q_ASSERT(layout.size() == m_thicksList.size());
256
257 switch (m_type)
258 {
259 case X_AXIS:
260 {
261 QGraphicsLineItem *lineItem = static_cast<QGraphicsLineItem*>(axis.at(0));
262 lineItem->setLine(m_rect.left(), m_rect.bottom(), m_rect.right(), m_rect.bottom());
263
264 for (int i = 0; i < layout.size(); ++i) {
265 QGraphicsLineItem *lineItem = static_cast<QGraphicsLineItem*>(lines.at(i));
266 lineItem->setLine(layout[i], m_rect.top(), layout[i], m_rect.bottom());
267 QGraphicsSimpleTextItem *labelItem = static_cast<QGraphicsSimpleTextItem*>(labels.at(i));
268 labelItem->setText(m_thicksList.at(i));
269 QPointF center = labelItem->boundingRect().center();
270 labelItem->setTransformOriginPoint(center.x(), center.y());
271 labelItem->setPos(layout[i] - center.x(), m_rect.bottom() + label_padding);
272 if(i%2 && i+1 < layout.size()){
273 QGraphicsRectItem *rectItem = static_cast<QGraphicsRectItem*>(shades.at(i/2));
274 rectItem->setRect(layout[i],m_rect.top(),layout[i+1]-layout[i],m_rect.height());
275 }
276 lineItem = static_cast<QGraphicsLineItem*>(axis.at(i+1));
277 lineItem->setLine(layout[i],m_rect.bottom(),layout[i],m_rect.bottom()+5);
278 }
279 }
280 break;
281
282 case Y_AXIS:
283 {
284 QGraphicsLineItem *lineItem = static_cast<QGraphicsLineItem*>(axis.at(0));
285 lineItem->setLine(m_rect.left() , m_rect.top(), m_rect.left(), m_rect.bottom());
286
287 for (int i = 0; i < layout.size(); ++i) {
288 QGraphicsLineItem *lineItem = static_cast<QGraphicsLineItem*>(lines.at(i));
289 lineItem->setLine(m_rect.left() , layout[i], m_rect.right(), layout[i]);
290 QGraphicsSimpleTextItem *labelItem = static_cast<QGraphicsSimpleTextItem*>(labels.at(i));
291 labelItem->setText(m_thicksList.at(i));
292 QPointF center = labelItem->boundingRect().center();
293 labelItem->setTransformOriginPoint(center.x(), center.y());
294 labelItem->setPos(m_rect.left() - labelItem->boundingRect().width() - label_padding , layout[i]-center.y());
295 if(i%2 && i+1 < layout.size()){
296 QGraphicsRectItem *rectItem = static_cast<QGraphicsRectItem*>(shades.at(i/2));
297 rectItem->setRect(m_rect.left(),layout[i],m_rect.width(),layout[i]-layout[i+1]);
298 }
299 lineItem = static_cast<QGraphicsLineItem*>(axis.at(i+1));
300 lineItem->setLine(m_rect.left()-5,layout[i],m_rect.left(),layout[i]);
301 }
302 }
303 break;
304 default:
305 qDebug()<<"Unknown axis type";
306 break;
307 }
308
309 m_layoutVector=layout;
310 }
309 }
311
310
312 //handlers
311 //handlers
313
312
314 void AxisItem::handleAxisCategoriesUpdated()
313 void AxisItem::handleAxisCategoriesUpdated()
315 {
314 {
316 updateItem();
315 if(isEmpty()) return;
316 m_ticksList = createLabels(m_ticksCount,m_min,m_max);
317 updateLayout(m_layoutVector);
317 }
318 }
318
319
319 void AxisItem::handleAxisUpdated()
320 void AxisItem::handleAxisUpdated()
@@ -321,9 +322,8 void AxisItem::handleAxisUpdated()
321
322
322 int count = m_chartAxis->ticksCount();
323 int count = m_chartAxis->ticksCount();
323
324
324 if(m_ticks!=count){
325 if(m_ticksCount!=count){
325 m_ticks=count;
326 handleTicksCountChanged(count);
326 updateItem();
327 }
327 }
328
328
329 if(isEmpty()) return;
329 if(isEmpty()) return;
@@ -368,6 +368,16 void AxisItem::handleAxisUpdated()
368
368
369 }
369 }
370
370
371 void AxisItem::handleTicksCountChanged(int count)
372 {
373 m_ticksCount=count;
374
375 if(isEmpty()) return;
376 m_ticksList = createLabels(m_ticksCount,m_min,m_max);
377 QVector<qreal> layout = calculateLayout();
378 updateLayout(layout);
379 }
380
371 void AxisItem::handleRangeChanged(qreal min, qreal max)
381 void AxisItem::handleRangeChanged(qreal min, qreal max)
372 {
382 {
373
383
@@ -375,20 +385,29 void AxisItem::handleRangeChanged(qreal min, qreal max)
375 m_max = max;
385 m_max = max;
376
386
377 if(isEmpty()) return;
387 if(isEmpty()) return;
378 updateItem();
388 m_ticksList = createLabels(m_ticksCount,m_min,m_max);
389 QVector<qreal> layout = calculateLayout();
390 updateLayout(layout);
379
391
380 }
392 }
381
393
382 void AxisItem::handleGeometryChanged(const QRectF& rect)
394 void AxisItem::handleGeometryChanged(const QRectF& rect)
383 {
395 {
396
384 m_rect = rect;
397 m_rect = rect;
385 if(isEmpty()) return;
398 if(isEmpty()) return;
386 updateItem();
399 m_ticksList = createLabels(m_ticksCount,m_min,m_max);
400 QVector<qreal> layout = calculateLayout();
401 updateLayout(layout);
387 }
402 }
388
403
389 bool AxisItem::isEmpty()
404 //painter
405
406 void AxisItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
390 {
407 {
391 return m_rect.isEmpty() || m_min==m_max || m_ticks==0;
408 Q_UNUSED(painter);
409 Q_UNUSED(option);
410 Q_UNUSED(widget);
392 }
411 }
393
412
394 //TODO "nice numbers algorithm"
413 //TODO "nice numbers algorithm"
@@ -50,22 +50,23 public:
50 void setLabelsFont(const QFont& font);
50 void setLabelsFont(const QFont& font);
51
51
52 public slots:
52 public slots:
53 void handleAxisUpdated();//qchartaxis update calls
53 void handleAxisUpdated();
54 void handleAxisCategoriesUpdated();//qchartaxis update calls
54 void handleAxisCategoriesUpdated();
55 void handleRangeChanged(qreal min , qreal max); //domain update calls
55 void handleRangeChanged(qreal min , qreal max);
56 void handleGeometryChanged(const QRectF& size); //geometry update calls
56 void handleTicksCountChanged(int count);
57 void handleGeometryChanged(const QRectF& size);
57
58
58 public:
59 public:
59 virtual void updateItem();
60 virtual void updateLayout(QVector<qreal>& layout);
60 QVector<qreal> calculateLayout() const;
61 void setLayout(QVector<qreal>& layout);
61 void setLayout(const QVector<qreal>& points);
62 QVector<qreal> layout() { return m_layoutVector;};
62 QVector<qreal> layout() { return m_layoutVector;};
63
63
64 private:
64 private:
65 inline bool isEmpty();
65 inline bool isEmpty();
66 void clear(int count);
67 void createItems(int count);
66 void createItems(int count);
68 QStringList createLabels(int ticks, qreal min, qreal max);
67 void deleteItems(int count);
68 QVector<qreal> calculateLayout() const;
69 QStringList createLabels(int ticks, qreal min, qreal max) const;
69
70
70 private:
71 private:
71 QChartAxis* m_chartAxis;
72 QChartAxis* m_chartAxis;
@@ -76,11 +77,11 private:
76 QGraphicsItemGroup m_shades;
77 QGraphicsItemGroup m_shades;
77 QGraphicsItemGroup m_labels;
78 QGraphicsItemGroup m_labels;
78 QGraphicsItemGroup m_axis;
79 QGraphicsItemGroup m_axis;
79 QStringList m_thicksList;
80 QStringList m_ticksList;
80 QVector<qreal> m_layoutVector;
81 QVector<qreal> m_layoutVector;
81 qreal m_min;
82 qreal m_min;
82 qreal m_max;
83 qreal m_max;
83 int m_ticks;
84 int m_ticksCount;
84
85
85 };
86 };
86
87
@@ -100,22 +100,23 void BarPresenterBase::initAxisLabels()
100 if (0 == count) {
100 if (0 == count) {
101 return;
101 return;
102 }
102 }
103 count++;
104
103
105 mChart->axisX()->setTicksCount(count);
104 mChart->axisX()->setTicksCount(count+2);
106
105
107 qreal min = 0;
106 qreal min = 0;
108 qreal max = count;
107 qreal max = count+1;
109
108
110 mChart->axisX()->setMin(min);
109 mChart->axisX()->setMin(min);
111 mChart->axisX()->setMax(max);
110 mChart->axisX()->setMax(max);
112 min++;
111
113 QChartAxisCategories* categories = mChart->axisX()->categories();
112 QChartAxisCategories* categories = mChart->axisX()->categories();
114 categories->clear();
113 categories->clear();
115 for (int i=0; i<count-1; i++) {
114 for (int i=0; i<count; i++) {
116 categories->insert(min,mSeries->categoryName(i));
115 categories->insert(i+1,mSeries->categoryName(i));
117 min++;
118 }
116 }
117
118
119
119 mChart->axisX()->setLabelsVisible(true);
120 mChart->axisX()->setLabelsVisible(true);
120 }
121 }
121
122
General Comments 0
You need to be logged in to leave comments. Login now