##// END OF EJS Templates
Bug fix for bar presenters. It appears that order of childItems may change. Relying on order caused crash
sauimone -
r256:bd68fc4fe7ab
parent child
Show More
@@ -5,8 +5,9
5 QTCOMMERCIALCHART_BEGIN_NAMESPACE
5 QTCOMMERCIALCHART_BEGIN_NAMESPACE
6
6
7 Bar::Bar(QGraphicsItem *parent)
7 Bar::Bar(QGraphicsItem *parent)
8 : ChartItem(parent)
8 : QGraphicsObject(parent)
9 {
9 {
10 setAcceptedMouseButtons(Qt::LeftButton);
10 }
11 }
11
12
12 void Bar::setSize(const QSizeF& size)
13 void Bar::setSize(const QSizeF& size)
@@ -18,7 +19,6 void Bar::setSize(const QSizeF& size)
18
19
19 void Bar::resize( qreal w, qreal h )
20 void Bar::resize( qreal w, qreal h )
20 {
21 {
21 // qDebug() << "bar::resize" << w << h;
22 mWidth = w;
22 mWidth = w;
23 mHeight = h;
23 mHeight = h;
24 }
24 }
@@ -30,7 +30,6 void Bar::setColor( QColor col )
30
30
31 void Bar::setPos(qreal x, qreal y)
31 void Bar::setPos(qreal x, qreal y)
32 {
32 {
33 // qDebug() << "Bar::setpos" << x << y;
34 mXpos = x;
33 mXpos = x;
35 mYpos = y;
34 mYpos = y;
36 }
35 }
@@ -50,10 +49,7 void Bar::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidg
50 if (0 == mHeight) {
49 if (0 == mHeight) {
51 return;
50 return;
52 }
51 }
53 // TODO: accept brush instead of color
54 painter->setBrush(mBrush);
52 painter->setBrush(mBrush);
55 // QBrush brush(mColor);
56 // painter->setBrush(brush);
57
53
58 // This compensates for rounding errors. drawRect takes ints and cumulative error of pos + size may be over 1.
54 // This compensates for rounding errors. drawRect takes ints and cumulative error of pos + size may be over 1.
59 int x0 = mXpos;
55 int x0 = mXpos;
@@ -71,6 +67,11 QRectF Bar::boundingRect() const
71 return r;
67 return r;
72 }
68 }
73
69
74 //#include "moc_bar_p.cpp"
70 void Bar::mousePressEvent(QGraphicsSceneMouseEvent* /*event*/)
71 {
72 emit clicked();
73 }
74
75 #include "moc_bar_p.cpp"
75
76
76 QTCOMMERCIALCHART_END_NAMESPACE
77 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,17 +1,17
1 #ifndef BAR_H
1 #ifndef BAR_H
2 #define BAR_H
2 #define BAR_H
3
3
4 #include "chartitem_p.h"
5 #include "qchartglobal.h"
4 #include "qchartglobal.h"
6 #include <QGraphicsItem>
5 #include <QGraphicsObject>
7 #include <QPen>
6 #include <QPen>
8 #include <QBrush>
7 #include <QBrush>
9
8
10 QTCOMMERCIALCHART_BEGIN_NAMESPACE
9 QTCOMMERCIALCHART_BEGIN_NAMESPACE
11
10
12 // Single bar item of chart
11 // Single bar item of chart
13 class Bar : public ChartItem
12 class Bar : public QGraphicsObject
14 {
13 {
14 Q_OBJECT
15 public:
15 public:
16 Bar(QGraphicsItem *parent=0);
16 Bar(QGraphicsItem *parent=0);
17
17
@@ -30,6 +30,10 public:
30
30
31 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
31 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
32 QRectF boundingRect() const;
32 QRectF boundingRect() const;
33 void mousePressEvent(QGraphicsSceneMouseEvent *event);
34
35 Q_SIGNALS:
36 void clicked();
33
37
34 private:
38 private:
35
39
@@ -14,7 +14,6 BarPresenter::BarPresenter(BarChartModel& model, QGraphicsItem *parent) :
14
14
15 void BarPresenter::layoutChanged()
15 void BarPresenter::layoutChanged()
16 {
16 {
17 // qDebug() << "BarGroup::layoutChanged";
18 // Scale bars to new layout
17 // Scale bars to new layout
19 // Layout for bars:
18 // Layout for bars:
20 if (mModel.countSets() <= 0) {
19 if (mModel.countSets() <= 0) {
@@ -23,7 +22,7 void BarPresenter::layoutChanged()
23 }
22 }
24
23
25 if (childItems().count() == 0) {
24 if (childItems().count() == 0) {
26 qDebug() << "WARNING: BarGroup::layoutChanged called before graphics items are created!";
25 qDebug() << "WARNING: BarPresenter::layoutChanged called before graphics items are created!";
27 return;
26 return;
28 }
27 }
29
28
@@ -41,14 +40,14 void BarPresenter::layoutChanged()
41
40
42 // Scaling.
41 // Scaling.
43 int itemIndex(0);
42 int itemIndex(0);
44 int labelIndex = itemCount * setCount;
43 int labelIndex(0);
45
44
46 for (int item=0; item < itemCount; item++) {
45 for (int item=0; item < itemCount; item++) {
47 qreal xPos = xStepPerSet * item + ((tW + mBarDefaultWidth*setCount)/(itemCount*2));
46 qreal xPos = xStepPerSet * item + ((tW + mBarDefaultWidth*setCount)/(itemCount*2));
48 qreal yPos = mHeight;
47 qreal yPos = mHeight;
49 for (int set = 0; set < setCount; set++) {
48 for (int set = 0; set < setCount; set++) {
50 qreal barHeight = mModel.valueAt(set, item) * scale;
49 qreal barHeight = mModel.valueAt(set, item) * scale;
51 Bar* bar = reinterpret_cast<Bar*> (childItems().at(itemIndex));
50 Bar* bar = mBars.at(itemIndex);
52
51
53 // TODO: width settable per bar?
52 // TODO: width settable per bar?
54 bar->resize(mBarDefaultWidth, barHeight);
53 bar->resize(mBarDefaultWidth, barHeight);
@@ -60,7 +59,7 void BarPresenter::layoutChanged()
60
59
61 // TODO: Layout for labels, remove magic number
60 // TODO: Layout for labels, remove magic number
62 xPos = xStepPerSet * item + ((tW + mBarDefaultWidth*setCount)/(itemCount*2));
61 xPos = xStepPerSet * item + ((tW + mBarDefaultWidth*setCount)/(itemCount*2));
63 BarLabel* label = reinterpret_cast<BarLabel*> (childItems().at(labelIndex));
62 BarLabel* label = mLabels.at(labelIndex);
64 label->setPos(xPos, mHeight + 20);
63 label->setPos(xPos, mHeight + 20);
65 labelIndex++;
64 labelIndex++;
66 }
65 }
@@ -7,8 +7,7
7
7
8 QTCOMMERCIALCHART_BEGIN_NAMESPACE
8 QTCOMMERCIALCHART_BEGIN_NAMESPACE
9
9
10 // Base class for bar groups
10 // Presenter for parallel bars. Grouping of bars is done on category basis.
11
12 class BarPresenter : public BarPresenterBase
11 class BarPresenter : public BarPresenterBase
13 {
12 {
14 public:
13 public:
@@ -25,9 +25,8 void BarPresenterBase::setSeparatorsVisible(bool visible)
25
25
26 void BarPresenterBase::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
26 void BarPresenterBase::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
27 {
27 {
28 // qDebug() << "BarGroupBase::paint" << childItems().count();
29 if (!mLayoutSet) {
28 if (!mLayoutSet) {
30 qDebug() << "BarGroupBase::paint called without layout set. Aborting.";
29 qDebug() << "BarPresenterBase::paint called without layout set. Aborting.";
31 return;
30 return;
32 }
31 }
33 // if (mLayoutDirty) {
32 // if (mLayoutDirty) {
@@ -51,19 +50,24 void BarPresenterBase::setBarWidth( int w )
51 void BarPresenterBase::dataChanged()
50 void BarPresenterBase::dataChanged()
52 {
51 {
53 // TODO: performance optimizations. Do we really need to delete and create items every time data is changed or can we reuse them?
52 // TODO: performance optimizations. Do we really need to delete and create items every time data is changed or can we reuse them?
54
53 qDebug() << "datachanged";
55 // Delete old bars
54 // Delete old bars
56 foreach (QGraphicsItem* item, childItems()) {
55 foreach (QGraphicsItem* item, childItems()) {
57 delete item;
56 delete item;
58 }
57 }
59
58
59 mBars.clear();
60 mLabels.clear();
61 mSeparators.clear();
62
60 // Create new graphic items for bars
63 // Create new graphic items for bars
61 for (int s=0; s<mModel.countSets(); s++) {
64 for (int s=0; s<mModel.countSets(); s++) {
62 QBarSet *set = mModel.nextSet(0==s);
65 QBarSet *set = mModel.nextSet(0==s);
63 for (int c=0; c<mModel.countCategories(); c++) {
66 for (int c=0; c<mModel.countCategories(); c++) {
64 Bar *bar = new Bar(this);
67 Bar *bar = new Bar(this);
65 childItems().append(bar);
68 childItems().append(bar);
66 //connect(bar,SIGNAL(clicked()),set,SLOT(barClicked()));
69 mBars.append(bar);
70 connect(bar,SIGNAL(clicked()),set,SLOT(barClicked()));
67 }
71 }
68 }
72 }
69
73
@@ -72,6 +76,7 void BarPresenterBase::dataChanged()
72 BarLabel* label = new BarLabel(this);
76 BarLabel* label = new BarLabel(this);
73 label->set(mModel.label(i));
77 label->set(mModel.label(i));
74 childItems().append(label);
78 childItems().append(label);
79 mLabels.append(label);
75 }
80 }
76
81
77 count = mModel.countCategories() - 1; // There is one less separator than columns
82 count = mModel.countCategories() - 1; // There is one less separator than columns
@@ -79,6 +84,7 void BarPresenterBase::dataChanged()
79 Separator* sep = new Separator(this);
84 Separator* sep = new Separator(this);
80 sep->setColor(QColor(255,0,0,255)); // TODO: color for separations from theme
85 sep->setColor(QColor(255,0,0,255)); // TODO: color for separations from theme
81 childItems().append(sep);
86 childItems().append(sep);
87 mSeparators.append(sep);
82 }
88 }
83
89
84 // TODO: if (autolayout) { layoutChanged() } or something
90 // TODO: if (autolayout) { layoutChanged() } or something
@@ -89,13 +95,13 void BarPresenterBase::dataChanged()
89
95
90 void BarPresenterBase::handleModelChanged(int index)
96 void BarPresenterBase::handleModelChanged(int index)
91 {
97 {
92 // qDebug() << "BarGroupBase::handleModelChanged" << index;
98 // qDebug() << "BarPresenterBase::handleModelChanged" << index;
93 dataChanged();
99 dataChanged();
94 }
100 }
95
101
96 void BarPresenterBase::handleDomainChanged(const Domain& domain)
102 void BarPresenterBase::handleDomainChanged(const Domain& domain)
97 {
103 {
98 // qDebug() << "BarGroupBase::handleDomainChanged";
104 // qDebug() << "BarPresenterBase::handleDomainChanged";
99 // TODO: Figure out the use case for this.
105 // TODO: Figure out the use case for this.
100 // Affects the size of visible item, so layout is changed.
106 // Affects the size of visible item, so layout is changed.
101 // layoutChanged();
107 // layoutChanged();
@@ -9,7 +9,11
9
9
10 QTCOMMERCIALCHART_BEGIN_NAMESPACE
10 QTCOMMERCIALCHART_BEGIN_NAMESPACE
11
11
12 // Base Class for bar groups. Common implemantation of different groups. Not to be instantiated.
12 class Bar;
13 class BarLabel;
14 class Separator;
15
16 // Common implemantation of different presenters. Not to be instantiated.
13 class BarPresenterBase : public QObject, public ChartItem
17 class BarPresenterBase : public QObject, public ChartItem
14 {
18 {
15 Q_OBJECT
19 Q_OBJECT
@@ -51,10 +55,14 protected:
51 bool mLayoutSet; // True, if component has been laid out.
55 bool mLayoutSet; // True, if component has been laid out.
52 bool mLayoutDirty;
56 bool mLayoutDirty;
53
57
54 QList<QColor> mColors; // List of colors for series for now
55 bool mSeparatorsVisible;
58 bool mSeparatorsVisible;
56 BarChartModel& mModel;
59 BarChartModel& mModel;
57
60
61 // Not owned.
62 QList<Bar*> mBars;
63 QList<BarLabel*> mLabels;
64 QList<Separator*> mSeparators;
65
58 QPen mPen;
66 QPen mPen;
59 };
67 };
60
68
@@ -15,7 +15,6 PercentBarPresenter::PercentBarPresenter(BarChartModel& model, QGraphicsItem *pa
15
15
16 void PercentBarPresenter::layoutChanged()
16 void PercentBarPresenter::layoutChanged()
17 {
17 {
18 // qDebug() << "PercentBarGroup::layoutChanged";
19 // Scale bars to new layout
18 // Scale bars to new layout
20 // Layout for bars:
19 // Layout for bars:
21 if (mModel.countSets() <= 0) {
20 if (mModel.countSets() <= 0) {
@@ -25,7 +24,7 void PercentBarPresenter::layoutChanged()
25 }
24 }
26
25
27 if (childItems().count() == 0) {
26 if (childItems().count() == 0) {
28 qDebug() << "WARNING: PercentBarGroup::layoutChanged called before graphics items are created!";
27 qDebug() << "WARNING: PercentBarPresenter::layoutChanged called before graphics items are created!";
29 return;
28 return;
30 }
29 }
31
30
@@ -33,11 +32,11 void PercentBarPresenter::layoutChanged()
33 // Use reals for accurancy (we might get some compiler warnings... :)
32 // Use reals for accurancy (we might get some compiler warnings... :)
34 int count = mModel.countCategories();
33 int count = mModel.countCategories();
35 int itemIndex(0);
34 int itemIndex(0);
35 int labelIndex(0);
36 qreal tW = mWidth;
36 qreal tW = mWidth;
37 qreal tC = count+1;
37 qreal tC = count+1;
38 qreal xStep = (tW/tC);
38 qreal xStep = (tW/tC);
39 qreal xPos = ((tW/tC) - mBarDefaultWidth / 2);
39 qreal xPos = ((tW/tC) - mBarDefaultWidth / 2);
40 int labelIndex = mModel.countCategories() * mModel.countSets();
41
40
42 for (int category = 0; category < mModel.countCategories(); category++) {
41 for (int category = 0; category < mModel.countCategories(); category++) {
43 qreal colSum = mModel.categorySum(category);
42 qreal colSum = mModel.categorySum(category);
@@ -46,7 +45,7 void PercentBarPresenter::layoutChanged()
46 qreal yPos = h;
45 qreal yPos = h;
47 for (int set=0; set < mModel.countSets(); set++) {
46 for (int set=0; set < mModel.countSets(); set++) {
48 qreal barHeight = mModel.valueAt(set, category) * scale;
47 qreal barHeight = mModel.valueAt(set, category) * scale;
49 Bar* bar = reinterpret_cast<Bar*> (childItems().at(itemIndex));
48 Bar* bar = mBars.at(itemIndex);
50
49
51 // TODO: width settable per bar?
50 // TODO: width settable per bar?
52 bar->resize(mBarDefaultWidth, barHeight);
51 bar->resize(mBarDefaultWidth, barHeight);
@@ -57,17 +56,17 void PercentBarPresenter::layoutChanged()
57 }
56 }
58
57
59 // TODO: Layout for labels, remove magic number
58 // TODO: Layout for labels, remove magic number
60 BarLabel* label = reinterpret_cast<BarLabel*> (childItems().at(labelIndex));
59 BarLabel* label = mLabels.at(labelIndex);
61 label->setPos(xPos, mHeight + 20);
60 label->setPos(xPos, mHeight + 20);
62 labelIndex++;
61 labelIndex++;
63 xPos += xStep;
62 xPos += xStep;
64 }
63 }
65
64
66 // Position separators
65 // Position separators
67 int separatorIndex = labelIndex; // Separators are after labels in childItems(). TODO: better way to store these?
66 int separatorIndex(0);
68 xPos = xStep + xStep/2; // Initial position is between first and second group. ie one and half steps from left.
67 xPos = xStep + xStep/2;
69 for (int s=0; s < mModel.countCategories() - 1; s++) {
68 for (int s=0; s < mModel.countCategories() - 1; s++) {
70 Separator* sep = reinterpret_cast<Separator*> (childItems().at(separatorIndex));
69 Separator* sep = mSeparators.at(separatorIndex);
71 sep->setPos(xPos,0);
70 sep->setPos(xPos,0);
72 sep->setSize(QSizeF(1,mHeight));
71 sep->setSize(QSizeF(1,mHeight));
73 xPos += xStep;
72 xPos += xStep;
@@ -14,7 +14,6 StackedBarPresenter::StackedBarPresenter(BarChartModel& model, QGraphicsItem *pa
14
14
15 void StackedBarPresenter::layoutChanged()
15 void StackedBarPresenter::layoutChanged()
16 {
16 {
17 // qDebug() << "StackedBarGroup::layoutChanged";
18 // Scale bars to new layout
17 // Scale bars to new layout
19 // Layout for bars:
18 // Layout for bars:
20 if (mModel.countSets() <= 0) {
19 if (mModel.countSets() <= 0) {
@@ -30,7 +29,7 void StackedBarPresenter::layoutChanged()
30 }
29 }
31
30
32 if (childItems().count() == 0) {
31 if (childItems().count() == 0) {
33 qDebug() << "WARNING: StackedBarGroup::layoutChanged called before graphics items are created!";
32 qDebug() << "WARNING: StackedBarPresenter::layoutChanged called before graphics items are created!";
34 return;
33 return;
35 }
34 }
36
35
@@ -42,17 +41,17 void StackedBarPresenter::layoutChanged()
42 qreal scale = (h / maxSum);
41 qreal scale = (h / maxSum);
43
42
44 int itemIndex(0);
43 int itemIndex(0);
44 int labelIndex(0);
45 qreal tW = mWidth;
45 qreal tW = mWidth;
46 qreal tC = mModel.countCategories() + 1;
46 qreal tC = mModel.countCategories() + 1;
47 qreal xStep = (tW/tC);
47 qreal xStep = (tW/tC);
48 qreal xPos = ((tW/tC) - mBarDefaultWidth / 2);
48 qreal xPos = ((tW/tC) - mBarDefaultWidth / 2);
49 int labelIndex = mModel.countSets() * mModel.countCategories();
50
49
51 for (int category = 0; category < mModel.countCategories(); category++) {
50 for (int category = 0; category < mModel.countCategories(); category++) {
52 qreal yPos = h;
51 qreal yPos = h;
53 for (int set=0; set < mModel.countSets(); set++) {
52 for (int set=0; set < mModel.countSets(); set++) {
54 qreal barHeight = mModel.valueAt(set, category) * scale;
53 qreal barHeight = mModel.valueAt(set, category) * scale;
55 Bar* bar = reinterpret_cast<Bar*> (childItems().at(itemIndex));
54 Bar* bar = mBars.at(itemIndex);
56
55
57 bar->resize(mBarDefaultWidth, barHeight);
56 bar->resize(mBarDefaultWidth, barHeight);
58 bar->setBrush(mModel.setAt(set).brush());
57 bar->setBrush(mModel.setAt(set).brush());
@@ -62,17 +61,17 void StackedBarPresenter::layoutChanged()
62 }
61 }
63
62
64 // TODO: Layout for labels, remove magic number
63 // TODO: Layout for labels, remove magic number
65 BarLabel* label = reinterpret_cast<BarLabel*> (childItems().at(labelIndex));
64 BarLabel* label = mLabels.at(labelIndex);
66 label->setPos(xPos, mHeight + 20);
65 label->setPos(xPos, mHeight + 20);
67 labelIndex++;
66 labelIndex++;
68 xPos += xStep;
67 xPos += xStep;
69 }
68 }
70
69
71 // Position separators
70 // Position separators
72 int separatorIndex = labelIndex; // Separators are after labels in childItems(). TODO: better way to store these?
71 int separatorIndex(0);
73 xPos = xStep + xStep/2; // Initial position is between first and second group. ie one and half steps from left.
72 xPos = xStep + xStep/2;
74 for (int s=0; s < mModel.countCategories() - 1; s++) {
73 for (int s=0; s < mModel.countCategories() - 1; s++) {
75 Separator* sep = reinterpret_cast<Separator*> (childItems().at(separatorIndex));
74 Separator* sep = mSeparators.at(separatorIndex);
76 sep->setPos(xPos,0);
75 sep->setPos(xPos,0);
77 sep->setSize(QSizeF(1,mHeight));
76 sep->setSize(QSizeF(1,mHeight));
78 xPos += xStep;
77 xPos += xStep;
@@ -1,5 +1,5
1 #ifndef STACKEDBARGROUP_H
1 #ifndef STACKEDBARPRESENTER_H
2 #define STACKEDBARGROUP_H
2 #define STACKEDBARPRESENTER_H
3
3
4 #include "barpresenterbase.h"
4 #include "barpresenterbase.h"
5 #include "qstackedbarchartseries.h"
5 #include "qstackedbarchartseries.h"
@@ -13,7 +13,7 public:
13 StackedBarPresenter(BarChartModel& model, QGraphicsItem *parent = 0);
13 StackedBarPresenter(BarChartModel& model, QGraphicsItem *parent = 0);
14
14
15 private:
15 private:
16 // From BarGroupBase
16 // From BarPresenterBase
17 void layoutChanged(); // layout has changed -> need to recalculate bar sizes
17 void layoutChanged(); // layout has changed -> need to recalculate bar sizes
18
18
19 private:
19 private:
@@ -23,4 +23,4 private:
23
23
24 QTCOMMERCIALCHART_END_NAMESPACE
24 QTCOMMERCIALCHART_END_NAMESPACE
25
25
26 #endif // STACKEDBARGROUP_H
26 #endif // STACKEDBARPRESENTER_H
General Comments 0
You need to be logged in to leave comments. Login now