##// END OF EJS Templates
bug fix in bar charts. Crashed, if layout was set before data. Also integrated to test app.
sauimone -
r165:2ff4f264aa68
parent child
Show More
@@ -1,159 +1,157
1 #include <limits.h>
1 #include <limits.h>
2 #include <QVector>
2 #include <QVector>
3 #include <QDebug>
3 #include <QDebug>
4 #include "barchartmodel_p.h"
4 #include "barchartmodel_p.h"
5
5
6 QTCOMMERCIALCHART_BEGIN_NAMESPACE
6 QTCOMMERCIALCHART_BEGIN_NAMESPACE
7
7
8 BarChartModel::BarChartModel(QObject *parent) :
8 BarChartModel::BarChartModel(QObject *parent) :
9 QObject(parent)
9 QObject(parent)
10 ,mRunningId(1)
10 ,mRunningId(1)
11 {
11 {
12 }
12 }
13
13
14 BarChartModel::~BarChartModel()
14 BarChartModel::~BarChartModel()
15 {
15 {
16 qDebug() << "BarChartModel::~BarChartModel";
16 // qDebug() << "BarChartModel::~BarChartModel";
17 foreach (DataContainer* c, mDataModel) {
17 foreach (DataContainer* c, mDataModel) {
18 delete c;
18 delete c;
19 }
19 }
20 }
20 }
21
21
22 int BarChartModel::addData(QList<qreal> data)
22 int BarChartModel::addData(QList<qreal> data)
23 {
23 {
24 qDebug() << "BarChartModel::addData" << data.count();
24 // qDebug() << "BarChartModel::addData" << data.count();
25 DataContainer* c = new DataContainer(data,mRunningId);
25 DataContainer* c = new DataContainer(data,mRunningId);
26 mDataModel.append(c);
26 mDataModel.append(c);
27 mRunningId++;
27 mRunningId++;
28 return mRunningId-1;
28 return mRunningId-1;
29 }
29 }
30
30
31 void BarChartModel::removeData(int id)
31 void BarChartModel::removeData(int id)
32 {
32 {
33 qDebug() << "BarChartModel::removeData";
33 // qDebug() << "BarChartModel::removeData";
34 foreach(DataContainer* c, mDataModel) {
34 foreach(DataContainer* c, mDataModel) {
35 if (c->mId == id) {
35 if (c->mId == id) {
36 mDataModel.removeOne(c);
36 mDataModel.removeOne(c);
37 delete c;
37 delete c;
38 }
38 }
39 }
39 }
40 }
40 }
41
41
42 int BarChartModel::countRows()
42 int BarChartModel::countRows()
43 {
43 {
44 qDebug() << "BarChartModel::countRows";
44 // qDebug() << "BarChartModel::countRows";
45 return mDataModel.count();
45 return mDataModel.count();
46 }
46 }
47
47
48 int BarChartModel::countColumns()
48 int BarChartModel::countColumns()
49 {
49 {
50 qDebug() << "BarChartModel::countColumns";
50 // qDebug() << "BarChartModel::countColumns";
51 int count(0);
51 int count(0);
52 for (int i=0; i<mDataModel.count(); i++){
52 for (int i=0; i<mDataModel.count(); i++){
53 // TODO: can we assume that all series have same number of values? If not. then which values are empty?
53 // TODO: can we assume that all series have same number of values? If not. then which values are empty?
54 int temp = mDataModel.at(i)->countColumns();
54 int temp = mDataModel.at(i)->countColumns();
55 if (temp > count) {
55 if (temp > count) {
56 count = temp;
56 count = temp;
57 }
57 }
58 }
58 }
59 return count;
59 return count;
60 }
60 }
61
61
62 int BarChartModel::countTotalItems()
62 int BarChartModel::countTotalItems()
63 {
63 {
64 qDebug() << "BarChartModel::countTotalItems";
64 // qDebug() << "BarChartModel::countTotalItems";
65 int total = mDataModel.count() * countColumns();
65 int total = mDataModel.count() * countColumns();
66 qDebug() << "BarChartModel::countTotalItems datamodel count" << mDataModel.count();
67 qDebug() << "BarChartModel::countTotalItems countColumns count" << countColumns();
68 return total;
66 return total;
69 }
67 }
70
68
71 int BarChartModel::min()
69 int BarChartModel::min()
72 {
70 {
73 qDebug() << "BarChartModel::min";
71 // qDebug() << "BarChartModel::min";
74 Q_ASSERT(mDataModel.count() > 0);
72 Q_ASSERT(mDataModel.count() > 0);
75 // TODO: make min and max members and update them when data changes.
73 // TODO: make min and max members and update them when data changes.
76 // This is slower since they are checked every time, even if data is same since previous call.
74 // This is slower since they are checked every time, even if data is same since previous call.
77 int min = INT_MAX;
75 int min = INT_MAX;
78
76
79 for (int i=0; i <mDataModel.count(); i++) {
77 for (int i=0; i <mDataModel.count(); i++) {
80 int itemCount = mDataModel.at(i)->countColumns();
78 int itemCount = mDataModel.at(i)->countColumns();
81 for (int j=0; j<itemCount; j++) {
79 for (int j=0; j<itemCount; j++) {
82 int temp = mDataModel.at(i)->valueAt(j);
80 int temp = mDataModel.at(i)->valueAt(j);
83 if (temp < min) {
81 if (temp < min) {
84 min = temp;
82 min = temp;
85 }
83 }
86 }
84 }
87 }
85 }
88 return min;
86 return min;
89 }
87 }
90
88
91 int BarChartModel::max()
89 int BarChartModel::max()
92 {
90 {
93 qDebug() << "BarChartModel::max";
91 // qDebug() << "BarChartModel::max";
94 Q_ASSERT(mDataModel.count() > 0);
92 Q_ASSERT(mDataModel.count() > 0);
95
93
96 // TODO: make min and max members and update them when data changes.
94 // TODO: make min and max members and update them when data changes.
97 // This is slower since they are checked every time, even if data is same since previous call.
95 // This is slower since they are checked every time, even if data is same since previous call.
98 int max = INT_MIN;
96 int max = INT_MIN;
99
97
100 for (int i=0; i <mDataModel.count(); i++) {
98 for (int i=0; i <mDataModel.count(); i++) {
101 int itemCount = mDataModel.at(i)->countColumns();
99 int itemCount = mDataModel.at(i)->countColumns();
102 for (int j=0; j<itemCount; j++) {
100 for (int j=0; j<itemCount; j++) {
103 int temp = mDataModel.at(i)->valueAt(j);
101 int temp = mDataModel.at(i)->valueAt(j);
104 if (temp > max) {
102 if (temp > max) {
105 max = temp;
103 max = temp;
106 }
104 }
107 }
105 }
108 }
106 }
109
107
110 return max;
108 return max;
111 }
109 }
112
110
113 qreal BarChartModel::valueAt(int series, int item)
111 qreal BarChartModel::valueAt(int series, int item)
114 {
112 {
115 qDebug() << "BarChartModel::valueAt" << series << item;
113 // qDebug() << "BarChartModel::valueAt" << series << item;
116 if ((series < 0) || (series >= mDataModel.count())) {
114 if ((series < 0) || (series >= mDataModel.count())) {
117 // No series, no value.
115 // No series, no value.
118 return 0;
116 return 0;
119 } else if ((item < 0) || (item >= mDataModel.at(series)->countColumns())) {
117 } else if ((item < 0) || (item >= mDataModel.at(series)->countColumns())) {
120 // No item, no value.
118 // No item, no value.
121 return 0;
119 return 0;
122 }
120 }
123
121
124 qDebug() << "ValueAt" << series << item << "=" << mDataModel.at(series)->valueAt(item);
122 // qDebug() << "ValueAt" << series << item << "=" << mDataModel.at(series)->valueAt(item);
125 return mDataModel.at(series)->valueAt(item);
123 return mDataModel.at(series)->valueAt(item);
126 }
124 }
127
125
128 qreal BarChartModel::columnSum(int column)
126 qreal BarChartModel::columnSum(int column)
129 {
127 {
130 qDebug() << "BarChartModel::columnSum";
128 // qDebug() << "BarChartModel::columnSum";
131 int sum(0);
129 int sum(0);
132 int count = mDataModel.count(); // Count rows
130 int count = mDataModel.count(); // Count rows
133
131
134 for (int row = 0; row < count; row++) {
132 for (int row = 0; row < count; row++) {
135 if (column < mDataModel.at(row)->countColumns()) {
133 if (column < mDataModel.at(row)->countColumns()) {
136 sum += mDataModel.at(row)->valueAt(column);
134 sum += mDataModel.at(row)->valueAt(column);
137 }
135 }
138 }
136 }
139 return sum;
137 return sum;
140 }
138 }
141
139
142 qreal BarChartModel::maxColumnSum()
140 qreal BarChartModel::maxColumnSum()
143 {
141 {
144 qDebug() << "BarChartModel::maxColumnSum";
142 // qDebug() << "BarChartModel::maxColumnSum";
145 int max = INT_MIN;
143 int max = INT_MIN;
146 int count = countColumns();
144 int count = countColumns();
147
145
148 for (int col=0; col<count; col++) {
146 for (int col=0; col<count; col++) {
149 int sum = columnSum(col);
147 int sum = columnSum(col);
150 if (sum > max) {
148 if (sum > max) {
151 max = sum;
149 max = sum;
152 }
150 }
153 }
151 }
154 return max;
152 return max;
155 }
153 }
156
154
157 #include "moc_barchartmodel_p.cpp"
155 #include "moc_barchartmodel_p.cpp"
158
156
159 QTCOMMERCIALCHART_END_NAMESPACE
157 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,65 +1,70
1 #include "bargroup.h"
1 #include "bargroup.h"
2 #include "bar_p.h"
2 #include "bar_p.h"
3 #include "barlabel_p.h"
3 #include "barlabel_p.h"
4 #include <QDebug>
4 #include <QDebug>
5
5
6 QTCOMMERCIALCHART_BEGIN_NAMESPACE
6 QTCOMMERCIALCHART_BEGIN_NAMESPACE
7
7
8 BarGroup::BarGroup(BarChartSeries& series, QGraphicsItem *parent) :
8 BarGroup::BarGroup(BarChartSeries& series, QGraphicsItem *parent) :
9 BarGroupBase(series,parent)
9 BarGroupBase(series,parent)
10 {
10 {
11 mBarDefaultWidth = 10;
11 mBarDefaultWidth = 10;
12 }
12 }
13
13
14 void BarGroup::layoutChanged()
14 void BarGroup::layoutChanged()
15 {
15 {
16 qDebug() << "BarGroup::layoutChanged";
16 qDebug() << "BarGroup::layoutChanged";
17 // Scale bars to new layout
17 // Scale bars to new layout
18 // Layout for bars:
18 // Layout for bars:
19 if (mModel.countRows() <= 0) {
19 if (mModel.countRows() <= 0) {
20 return;
20 return;
21 }
21 }
22
22
23 if (childItems().count() == 0) {
24 qDebug() << "WARNING: BarGroup::layoutChanged called before graphics items are created!";
25 return;
26 }
27
23 // TODO: better way to auto-layout?
28 // TODO: better way to auto-layout?
24 // Use reals for accurancy (we might get some compiler warnings... :)
29 // Use reals for accurancy (we might get some compiler warnings... :)
25 int itemCount = mModel.countColumns();
30 int itemCount = mModel.countColumns();
26 int seriesCount = mModel.countRows();
31 int seriesCount = mModel.countRows();
27
32
28 qreal tW = mWidth;
33 qreal tW = mWidth;
29 qreal tH = mHeight;
34 qreal tH = mHeight;
30 qreal tM = mMax;
35 qreal tM = mMax;
31 qreal scale = (tH/tM);
36 qreal scale = (tH/tM);
32
37
33 qreal tC = itemCount+1;
38 qreal tC = itemCount+1;
34 qreal xStepPerSeries = (tW/tC);
39 qreal xStepPerSeries = (tW/tC);
35
40
36 // Scaling.
41 // Scaling.
37 int itemIndex(0);
42 int itemIndex(0);
38 int labelIndex = itemCount * seriesCount;
43 int labelIndex = itemCount * seriesCount;
39
44
40 for (int item=0; item < itemCount; item++) {
45 for (int item=0; item < itemCount; item++) {
41 qreal xPos = xStepPerSeries * item + ((tW + mBarDefaultWidth*seriesCount)/(itemCount*2));
46 qreal xPos = xStepPerSeries * item + ((tW + mBarDefaultWidth*seriesCount)/(itemCount*2));
42 qreal yPos = mHeight;
47 qreal yPos = mHeight;
43 for (int series = 0; series < seriesCount; series++) {
48 for (int series = 0; series < seriesCount; series++) {
44 qreal barHeight = mModel.valueAt(series, item) * scale;
49 qreal barHeight = mModel.valueAt(series, item) * scale;
45 Bar* bar = reinterpret_cast<Bar*> (childItems().at(itemIndex));
50 Bar* bar = reinterpret_cast<Bar*> (childItems().at(itemIndex));
46
51
47 // TODO: width settable per bar?
52 // TODO: width settable per bar?
48 bar->resize(mBarDefaultWidth, barHeight);
53 bar->resize(mBarDefaultWidth, barHeight);
49 bar->setColor(mColors.at(series));
54 bar->setColor(mColors.at(series));
50 bar->setPos(xPos, yPos-barHeight); // item*posStep+startPos + series * mBarDefaultWidth, mHeight);
55 bar->setPos(xPos, yPos-barHeight); // item*posStep+startPos + series * mBarDefaultWidth, mHeight);
51 itemIndex++;
56 itemIndex++;
52 xPos += mBarDefaultWidth;
57 xPos += mBarDefaultWidth;
53 }
58 }
54
59
55 // TODO: Layout for labels, remove magic number
60 // TODO: Layout for labels, remove magic number
56 xPos = xStepPerSeries * item + ((tW + mBarDefaultWidth*seriesCount)/(itemCount*2));
61 xPos = xStepPerSeries * item + ((tW + mBarDefaultWidth*seriesCount)/(itemCount*2));
57 BarLabel* label = reinterpret_cast<BarLabel*> (childItems().at(labelIndex));
62 BarLabel* label = reinterpret_cast<BarLabel*> (childItems().at(labelIndex));
58 label->setPos(xPos, mHeight + 20);
63 label->setPos(xPos, mHeight + 20);
59 labelIndex++;
64 labelIndex++;
60 }
65 }
61
66
62 mLayoutDirty = true;
67 mLayoutDirty = true;
63 }
68 }
64
69
65 QTCOMMERCIALCHART_END_NAMESPACE
70 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,133 +1,127
1 #include "bargroupbase.h"
1 #include "bargroupbase.h"
2 #include "bar_p.h"
2 #include "bar_p.h"
3 #include "barlabel_p.h"
3 #include "barlabel_p.h"
4 #include "separator_p.h"
4 #include "separator_p.h"
5 #include "barchartseriesbase.h"
5 #include "barchartseriesbase.h"
6 #include <QDebug>
6 #include <QDebug>
7
7
8 QTCOMMERCIALCHART_BEGIN_NAMESPACE
8 QTCOMMERCIALCHART_BEGIN_NAMESPACE
9
9
10 BarGroupBase::BarGroupBase(BarChartSeriesBase& series, QGraphicsItem *parent)
10 BarGroupBase::BarGroupBase(BarChartSeriesBase& series, QGraphicsItem *parent)
11 : ChartItem(parent)
11 : ChartItem(parent)
12 ,mBarDefaultWidth(20) // TODO: remove hard coding, when we have layout code ready
12 ,mBarDefaultWidth(20) // TODO: remove hard coding, when we have layout code ready
13 ,mLayoutSet(false)
13 ,mLayoutSet(false)
14 ,mLayoutDirty(true)
14 ,mLayoutDirty(true)
15 ,mTheme(0)
15 ,mTheme(0)
16 ,mSeparatorsVisible(true)
16 ,mSeparatorsVisible(true)
17 ,mModel(series.model())
17 ,mModel(series.model())
18 {
18 {
19 }
19 }
20
20
21 void BarGroupBase::setSeparatorsVisible(bool visible)
21 void BarGroupBase::setSeparatorsVisible(bool visible)
22 {
22 {
23 mSeparatorsVisible = visible;
23 mSeparatorsVisible = visible;
24 }
24 }
25
25
26 void BarGroupBase::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
26 void BarGroupBase::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
27 {
27 {
28 qDebug() << "BarGroupBase::paint" << childItems().count();
28 // qDebug() << "BarGroupBase::paint" << childItems().count();
29 if (!mLayoutSet) {
29 if (!mLayoutSet) {
30 qDebug() << "BarGroupBase::paint called without layout set. Aborting.";
30 qDebug() << "BarGroupBase::paint called without layout set. Aborting.";
31 return;
31 return;
32 }
32 }
33 // if (mLayoutDirty) {
33 // if (mLayoutDirty) {
34 // Layout or data has changed. Need to redraw.
34 // Layout or data has changed. Need to redraw.
35 foreach(QGraphicsItem* i, childItems()) {
35 foreach(QGraphicsItem* i, childItems()) {
36 i->paint(painter,option,widget);
36 i->paint(painter,option,widget);
37 }
37 }
38 // }
38 // }
39 }
39 }
40
40
41 QRectF BarGroupBase::boundingRect() const
41 QRectF BarGroupBase::boundingRect() const
42 {
42 {
43 return QRectF(0,0,mWidth,mHeight);
43 return QRectF(0,0,mWidth,mHeight);
44 }
44 }
45 /*
45
46 void BarGroupBase::themeChanged(ChartTheme *theme)
47 {
48 qDebug() << "BarGroupBase::themeChanged"
49 // mTheme = theme;
50 }
51 */
52 void BarGroupBase::setBarWidth( int w )
46 void BarGroupBase::setBarWidth( int w )
53 {
47 {
54 mBarDefaultWidth = w;
48 mBarDefaultWidth = w;
55 }
49 }
56
50
57 int BarGroupBase::addColor( QColor color )
51 int BarGroupBase::addColor( QColor color )
58 {
52 {
59 qDebug() << "BarGroupBase::addColor";
53 // qDebug() << "BarGroupBase::addColor";
60 int colorIndex = mColors.count();
54 int colorIndex = mColors.count();
61 mColors.append(color);
55 mColors.append(color);
62 return colorIndex;
56 return colorIndex;
63 }
57 }
64
58
65 void BarGroupBase::resetColors()
59 void BarGroupBase::resetColors()
66 {
60 {
67 qDebug() << "BarGroupBase::resetColors";
61 // qDebug() << "BarGroupBase::resetColors";
68 mColors.clear();
62 mColors.clear();
69 }
63 }
70
64
71 void BarGroupBase::dataChanged()
65 void BarGroupBase::dataChanged()
72 {
66 {
73 qDebug() << "BarGroupBase::dataChanged";
67 // qDebug() << "BarGroupBase::dataChanged";
74
68
75 // Delete old bars
69 // Delete old bars
76 foreach (QGraphicsItem* item, childItems()) {
70 foreach (QGraphicsItem* item, childItems()) {
77 delete item;
71 delete item;
78 }
72 }
79
73
80 // Create new graphic items for bars
74 // Create new graphic items for bars
81 int totalItems = mModel.countTotalItems(); // mSeries.countTotalItems();
75 int totalItems = mModel.countTotalItems(); // mSeries.countTotalItems();
82 for (int i=0; i<totalItems; i++) {
76 for (int i=0; i<totalItems; i++) {
83 Bar *bar = new Bar(this);
77 Bar *bar = new Bar(this);
84 childItems().append(bar);
78 childItems().append(bar);
85 }
79 }
86
80
87 // TODO: labels from series. This creates just some example labels
81 // TODO: labels from series. This creates just some example labels
88 int count = mModel.countColumns(); // mSeries.countColumns();
82 int count = mModel.countColumns(); // mSeries.countColumns();
89 for (int i=0; i<count; i++) {
83 for (int i=0; i<count; i++) {
90 BarLabel* label = new BarLabel(this);
84 BarLabel* label = new BarLabel(this);
91 QString text("Label " + QString::number(i));
85 QString text("Label " + QString::number(i));
92 label->set(text);
86 label->set(text);
93 childItems().append(label);
87 childItems().append(label);
94 }
88 }
95
89
96 count = mModel.countColumns() - 1; // mSeries.countColumns() - 1; // There is one less separator than columns
90 count = mModel.countColumns() - 1; // mSeries.countColumns() - 1; // There is one less separator than columns
97 for (int i=0; i<count; i++) {
91 for (int i=0; i<count; i++) {
98 Separator* sep = new Separator(this);
92 Separator* sep = new Separator(this);
99 sep->setColor(QColor(255,0,0,255)); // TODO: color for separations from theme
93 sep->setColor(QColor(255,0,0,255)); // TODO: color for separations from theme
100 childItems().append(sep);
94 childItems().append(sep);
101 }
95 }
102
96
103 // TODO: if (autolayout) { layoutChanged() } or something
97 // TODO: if (autolayout) { layoutChanged() } or something
104 mLayoutDirty = true;
98 mLayoutDirty = true;
105 }
99 }
106
100
107 //handlers
101 //handlers
108
102
109 void BarGroupBase::handleModelChanged(int index)
103 void BarGroupBase::handleModelChanged(int index)
110 {
104 {
111 qDebug() << "BarGroupBase::handleModelChanged" << index;
105 // qDebug() << "BarGroupBase::handleModelChanged" << index;
112 dataChanged();
106 dataChanged();
113 }
107 }
114
108
115 void BarGroupBase::handleDomainChanged(const Domain& domain)
109 void BarGroupBase::handleDomainChanged(const Domain& domain)
116 {
110 {
117 qDebug() << "BarGroupBase::handleDomainChanged";
111 // qDebug() << "BarGroupBase::handleDomainChanged";
118 dataChanged();
112 dataChanged();
119 }
113 }
120
114
121 void BarGroupBase::handleGeometryChanged(const QRectF& rect)
115 void BarGroupBase::handleGeometryChanged(const QRectF& rect)
122 {
116 {
123 qDebug() << "BarGroupBase::handleGeometryChanged";
117 // qDebug() << "BarGroupBase::handleGeometryChanged";
124 mWidth = rect.width();
118 mWidth = rect.width();
125 mHeight = rect.height();
119 mHeight = rect.height();
126 layoutChanged();
120 layoutChanged();
127 mLayoutSet = true;
121 mLayoutSet = true;
128 setPos(rect.topLeft());
122 setPos(rect.topLeft());
129 }
123 }
130
124
131 #include "moc_bargroupbase.cpp"
125 #include "moc_bargroupbase.cpp"
132
126
133 QTCOMMERCIALCHART_END_NAMESPACE
127 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,73 +1,77
1 #include "percentbargroup.h"
1 #include "percentbargroup.h"
2 #include "bar_p.h"
2 #include "bar_p.h"
3 #include "barlabel_p.h"
3 #include "barlabel_p.h"
4 #include "separator_p.h"
4 #include "separator_p.h"
5 #include <QDebug>
5 #include <QDebug>
6
6
7 QTCOMMERCIALCHART_BEGIN_NAMESPACE
7 QTCOMMERCIALCHART_BEGIN_NAMESPACE
8
8
9
9
10 PercentBarGroup::PercentBarGroup(PercentBarChartSeries& series, QGraphicsItem *parent) :
10 PercentBarGroup::PercentBarGroup(PercentBarChartSeries& series, QGraphicsItem *parent) :
11 BarGroupBase(series, parent)
11 BarGroupBase(series, parent)
12 {
12 {
13 }
13 }
14
14
15 void PercentBarGroup::layoutChanged()
15 void PercentBarGroup::layoutChanged()
16 {
16 {
17 // Scale bars to new layout
17 // Scale bars to new layout
18 // Layout for bars:
18 // Layout for bars:
19 if (mModel.countRows() <= 0) {
19 if (mModel.countRows() <= 0) {
20 // Nothing to do.
20 // Nothing to do.
21 return;
21 return;
22 }
22 }
23
23
24 if (childItems().count() == 0) {
25 qDebug() << "WARNING: PercentBarGroup::layoutChanged called before graphics items are created!";
26 return;
27 }
28
24 // TODO: better way to auto-layout
29 // TODO: better way to auto-layout
25 // Use reals for accurancy (we might get some compiler warnings... :)
30 // Use reals for accurancy (we might get some compiler warnings... :)
26 int count = mModel.countColumns();
31 int count = mModel.countColumns();
27 int itemIndex(0);
32 int itemIndex(0);
28 qreal tW = mWidth;
33 qreal tW = mWidth;
29 qreal tC = count+1;
34 qreal tC = count+1;
30 qreal xStep = (tW/tC);
35 qreal xStep = (tW/tC);
31 // qreal xPos = ((tW/tC) + mBarDefaultWidth / 2);
32 qreal xPos = ((tW/tC) - mBarDefaultWidth / 2);
36 qreal xPos = ((tW/tC) - mBarDefaultWidth / 2);
33 int labelIndex = mModel.countColumns() * mModel.countRows();
37 int labelIndex = mModel.countColumns() * mModel.countRows();
34
38
35 for (int column = 0; column < mModel.countColumns(); column++) {
39 for (int column = 0; column < mModel.countColumns(); column++) {
36 qreal colSum = mModel.columnSum(column);
40 qreal colSum = mModel.columnSum(column);
37 qreal h = mHeight;
41 qreal h = mHeight;
38 qreal scale = (h / colSum);
42 qreal scale = (h / colSum);
39 qreal yPos = h;
43 qreal yPos = h;
40 for (int row=0; row < mModel.countRows(); row++) {
44 for (int row=0; row < mModel.countRows(); row++) {
41 qreal barHeight = mModel.valueAt(row, column) * scale;
45 qreal barHeight = mModel.valueAt(row, column) * scale;
42 Bar* bar = reinterpret_cast<Bar*> (childItems().at(itemIndex));
46 Bar* bar = reinterpret_cast<Bar*> (childItems().at(itemIndex));
43
47
44 // TODO: width settable per bar?
48 // TODO: width settable per bar?
45 bar->resize(mBarDefaultWidth, barHeight);
49 bar->resize(mBarDefaultWidth, barHeight);
46 bar->setColor(mColors.at(row));
50 bar->setColor(mColors.at(row));
47 bar->setPos(xPos, yPos-barHeight);
51 bar->setPos(xPos, yPos-barHeight);
48 itemIndex++;
52 itemIndex++;
49 yPos -= barHeight;
53 yPos -= barHeight;
50 }
54 }
51
55
52 // TODO: Layout for labels, remove magic number
56 // TODO: Layout for labels, remove magic number
53 BarLabel* label = reinterpret_cast<BarLabel*> (childItems().at(labelIndex));
57 BarLabel* label = reinterpret_cast<BarLabel*> (childItems().at(labelIndex));
54 label->setPos(xPos, mHeight + 20);
58 label->setPos(xPos, mHeight + 20);
55 labelIndex++;
59 labelIndex++;
56 xPos += xStep;
60 xPos += xStep;
57 }
61 }
58
62
59 // Position separators
63 // Position separators
60 int separatorIndex = labelIndex; // Separators are after labels in childItems(). TODO: better way to store these?
64 int separatorIndex = labelIndex; // Separators are after labels in childItems(). TODO: better way to store these?
61 xPos = xStep + xStep/2; // Initial position is between first and second group. ie one and half steps from left.
65 xPos = xStep + xStep/2; // Initial position is between first and second group. ie one and half steps from left.
62 for (int s=0; s < mModel.countColumns() - 1; s++) {
66 for (int s=0; s < mModel.countColumns() - 1; s++) {
63 Separator* sep = reinterpret_cast<Separator*> (childItems().at(separatorIndex));
67 Separator* sep = reinterpret_cast<Separator*> (childItems().at(separatorIndex));
64 sep->setPos(xPos,0);
68 sep->setPos(xPos,0);
65 sep->setSize(QSizeF(1,mHeight));
69 sep->setSize(QSizeF(1,mHeight));
66 xPos += xStep;
70 xPos += xStep;
67 separatorIndex++;
71 separatorIndex++;
68 }
72 }
69
73
70 mLayoutDirty = true;
74 mLayoutDirty = true;
71 }
75 }
72
76
73 QTCOMMERCIALCHART_END_NAMESPACE
77 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,81 +1,86
1 #include "stackedbargroup.h"
1 #include "stackedbargroup.h"
2 #include "bar_p.h"
2 #include "bar_p.h"
3 #include "barlabel_p.h"
3 #include "barlabel_p.h"
4 #include "separator_p.h"
4 #include "separator_p.h"
5 #include <QDebug>
5 #include <QDebug>
6
6
7 QTCOMMERCIALCHART_BEGIN_NAMESPACE
7 QTCOMMERCIALCHART_BEGIN_NAMESPACE
8
8
9 StackedBarGroup::StackedBarGroup(StackedBarChartSeries& series, QGraphicsItem *parent) :
9 StackedBarGroup::StackedBarGroup(StackedBarChartSeries& series, QGraphicsItem *parent) :
10 BarGroupBase(series,parent)
10 BarGroupBase(series,parent)
11 {
11 {
12 }
12 }
13
13
14 void StackedBarGroup::layoutChanged()
14 void StackedBarGroup::layoutChanged()
15 {
15 {
16 qDebug() << "StackedBarGroup::layoutChanged";
16 qDebug() << "StackedBarGroup::layoutChanged";
17 // Scale bars to new layout
17 // Scale bars to new layout
18 // Layout for bars:
18 // Layout for bars:
19 if (mModel.countRows() <= 0) {
19 if (mModel.countRows() <= 0) {
20 // Nothing to do.
20 // Nothing to do.
21 return;
21 return;
22 }
22 }
23
23
24 if (mModel.countColumns() == 0) {
24 if (mModel.countColumns() == 0) {
25 // Nothing to do
25 // Nothing to do
26 return;
26 return;
27 }
27 }
28
28
29 if (childItems().count() == 0) {
30 qDebug() << "WARNING: StackedBarGroup::layoutChanged called before graphics items are created!";
31 return;
32 }
33
29 // TODO: better way to auto-layout
34 // TODO: better way to auto-layout
30 // Use reals for accurancy (we might get some compiler warnings... :)
35 // Use reals for accurancy (we might get some compiler warnings... :)
31 // TODO: use temp variable for column count...
36 // TODO: use temp variable for column count...
32 qreal maxSum = mModel.maxColumnSum();
37 qreal maxSum = mModel.maxColumnSum();
33 qreal h = mHeight;
38 qreal h = mHeight;
34 qreal scale = (h / maxSum);
39 qreal scale = (h / maxSum);
35
40
36 int itemIndex(0);
41 int itemIndex(0);
37 qreal tW = mWidth;
42 qreal tW = mWidth;
38 qreal tC = mModel.countColumns() + 1;
43 qreal tC = mModel.countColumns() + 1;
39 qreal xStep = (tW/tC);
44 qreal xStep = (tW/tC);
40 qreal xPos = ((tW/tC) - mBarDefaultWidth / 2);
45 qreal xPos = ((tW/tC) - mBarDefaultWidth / 2);
41 int labelIndex = mModel.countRows() * mModel.countColumns();
46 int labelIndex = mModel.countRows() * mModel.countColumns();
42
47
43 for (int column = 0; column < mModel.countColumns(); column++) {
48 for (int column = 0; column < mModel.countColumns(); column++) {
44 qreal yPos = h;
49 qreal yPos = h;
45 for (int row=0; row < mModel.countRows(); row++) {
50 for (int row=0; row < mModel.countRows(); row++) {
46 qreal barHeight = mModel.valueAt(row, column) * scale;
51 qreal barHeight = mModel.valueAt(row, column) * scale;
47 Bar* bar = reinterpret_cast<Bar*> (childItems().at(itemIndex));
52 Bar* bar = reinterpret_cast<Bar*> (childItems().at(itemIndex));
48
53
49 // TODO: width settable per bar?
54 // TODO: width settable per bar?
50 // TODO: theme stuff
55 // TODO: theme stuff
51 // mTheme->themeForSeries();
56 // mTheme->themeForSeries();
52 bar->resize(mBarDefaultWidth, barHeight);
57 bar->resize(mBarDefaultWidth, barHeight);
53 bar->setColor(mColors.at(row));
58 bar->setColor(mColors.at(row));
54 bar->setPos(xPos, yPos-barHeight);
59 bar->setPos(xPos, yPos-barHeight);
55 itemIndex++;
60 itemIndex++;
56 yPos -= barHeight;
61 yPos -= barHeight;
57 }
62 }
58
63
59 // TODO: Layout for labels, remove magic number
64 // TODO: Layout for labels, remove magic number
60 BarLabel* label = reinterpret_cast<BarLabel*> (childItems().at(labelIndex));
65 BarLabel* label = reinterpret_cast<BarLabel*> (childItems().at(labelIndex));
61 label->setPos(xPos, mHeight + 20);
66 label->setPos(xPos, mHeight + 20);
62 labelIndex++;
67 labelIndex++;
63 xPos += xStep;
68 xPos += xStep;
64 }
69 }
65
70
66
71
67 // Position separators
72 // Position separators
68 int separatorIndex = labelIndex; // Separators are after labels in childItems(). TODO: better way to store these?
73 int separatorIndex = labelIndex; // Separators are after labels in childItems(). TODO: better way to store these?
69 xPos = xStep + xStep/2; // Initial position is between first and second group. ie one and half steps from left.
74 xPos = xStep + xStep/2; // Initial position is between first and second group. ie one and half steps from left.
70 for (int s=0; s < mModel.countColumns() - 1; s++) {
75 for (int s=0; s < mModel.countColumns() - 1; s++) {
71 Separator* sep = reinterpret_cast<Separator*> (childItems().at(separatorIndex));
76 Separator* sep = reinterpret_cast<Separator*> (childItems().at(separatorIndex));
72 sep->setPos(xPos,0);
77 sep->setPos(xPos,0);
73 sep->setSize(QSizeF(1,mHeight));
78 sep->setSize(QSizeF(1,mHeight));
74 xPos += xStep;
79 xPos += xStep;
75 separatorIndex++;
80 separatorIndex++;
76 }
81 }
77
82
78 mLayoutDirty = true;
83 mLayoutDirty = true;
79 }
84 }
80
85
81 QTCOMMERCIALCHART_END_NAMESPACE
86 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,62 +1,65
1 #include "dataseriedialog.h"
1 #include "dataseriedialog.h"
2 #include <QDialogButtonBox>
2 #include <QDialogButtonBox>
3 #include <QGridLayout>
3 #include <QGridLayout>
4 #include <QComboBox>
4 #include <QComboBox>
5 #include <QPushButton>
5 #include <QPushButton>
6 #include <QLabel>
6 #include <QLabel>
7 #include <QDebug>
7 #include <QDebug>
8
8
9 DataSerieDialog::DataSerieDialog(QString defaultType, QWidget *parent) :
9 DataSerieDialog::DataSerieDialog(QString defaultType, QWidget *parent) :
10 QDialog(parent)
10 QDialog(parent)
11 {
11 {
12 // Combo box for selecting the series type
12 // Combo box for selecting the series type
13 m_seriesTypeCombo = new QComboBox(this);
13 m_seriesTypeCombo = new QComboBox(this);
14 m_seriesTypeCombo->addItem("Line");
14 m_seriesTypeCombo->addItem("Line");
15 m_seriesTypeCombo->addItem("Area");
15 m_seriesTypeCombo->addItem("Area");
16 m_seriesTypeCombo->addItem("Bar");
16 m_seriesTypeCombo->addItem("Bar");
17 m_seriesTypeCombo->addItem("StackedBar");
18 m_seriesTypeCombo->addItem("PercentBar");
17 m_seriesTypeCombo->addItem("Pie");
19 m_seriesTypeCombo->addItem("Pie");
18 m_seriesTypeCombo->addItem("Scatter");
20 m_seriesTypeCombo->addItem("Scatter");
19 m_seriesTypeCombo->addItem("Spline");
21 m_seriesTypeCombo->addItem("Spline");
20
22
21 // Allow pre-selection of a series type
23 // Allow pre-selection of a series type
22 if (defaultType != "") {
24 if (defaultType != "") {
23 int index = m_seriesTypeCombo->findText(defaultType);
25 int index = m_seriesTypeCombo->findText(defaultType);
24 if (index > 0)
26 if (index > 0)
25 m_seriesTypeCombo->setCurrentIndex(index);
27 m_seriesTypeCombo->setCurrentIndex(index);
26 }
28 }
27
29
28 // Combo box for selecting data for the new series
30 // Combo box for selecting data for the new series
29 m_testDataCombo = new QComboBox(this);
31 m_testDataCombo = new QComboBox(this);
30 m_testDataCombo->addItem("linear");
32 m_testDataCombo->addItem("linear");
31 m_testDataCombo->addItem("linear, 1M");
33 m_testDataCombo->addItem("linear, 1M");
32 m_testDataCombo->addItem("SIN");
34 m_testDataCombo->addItem("SIN");
33 m_testDataCombo->addItem("SIN + random");
35 m_testDataCombo->addItem("SIN + random");
36 m_testDataCombo->addItem("Table, 5 series");
34 m_testDataCombo->addItem("TODO From file...");
37 m_testDataCombo->addItem("TODO From file...");
35 m_testDataCombo->addItem("TODO From URL...");
38 m_testDataCombo->addItem("TODO From URL...");
36
39
37 QDialogButtonBox *addSeriesBox = new QDialogButtonBox(Qt::Horizontal);
40 QDialogButtonBox *addSeriesBox = new QDialogButtonBox(Qt::Horizontal);
38 QPushButton *b = addSeriesBox->addButton(QDialogButtonBox::Ok);
41 QPushButton *b = addSeriesBox->addButton(QDialogButtonBox::Ok);
39 connect(b, SIGNAL(clicked()), this, SLOT(accept()));
42 connect(b, SIGNAL(clicked()), this, SLOT(accept()));
40 b = addSeriesBox->addButton(QDialogButtonBox::Cancel);
43 b = addSeriesBox->addButton(QDialogButtonBox::Cancel);
41 connect(b, SIGNAL(clicked()), this, SLOT(reject()));
44 connect(b, SIGNAL(clicked()), this, SLOT(reject()));
42
45
43 QGridLayout *grid = new QGridLayout();
46 QGridLayout *grid = new QGridLayout();
44 grid->addWidget(new QLabel("Series type:"), 0, 0);
47 grid->addWidget(new QLabel("Series type:"), 0, 0);
45 grid->addWidget(m_seriesTypeCombo, 0, 1);
48 grid->addWidget(m_seriesTypeCombo, 0, 1);
46 grid->addWidget(new QLabel("Data:"), 1, 0);
49 grid->addWidget(new QLabel("Data:"), 1, 0);
47 grid->addWidget(m_testDataCombo, 1, 1);
50 grid->addWidget(m_testDataCombo, 1, 1);
48 grid->addWidget(addSeriesBox, 2, 1);
51 grid->addWidget(addSeriesBox, 2, 1);
49
52
50 setLayout(grid);
53 setLayout(grid);
51 }
54 }
52
55
53 void DataSerieDialog::accept()
56 void DataSerieDialog::accept()
54 {
57 {
55 accepted(m_seriesTypeCombo->currentText(), m_testDataCombo->currentText());
58 accepted(m_seriesTypeCombo->currentText(), m_testDataCombo->currentText());
56 QDialog::accept();
59 QDialog::accept();
57 }
60 }
58 //void DataSerieDialog::addSeries(QAbstractButton *button)
61 //void DataSerieDialog::addSeries(QAbstractButton *button)
59 //{
62 //{
60 // addSeries(button->text().toAscii());
63 // addSeries(button->text().toAscii());
61 // accept();
64 // accept();
62 //}
65 //}
@@ -1,379 +1,401
1 #include "mainwidget.h"
1 #include "mainwidget.h"
2 #include "dataseriedialog.h"
2 #include "dataseriedialog.h"
3 #include "qchartseries.h"
3 #include "qchartseries.h"
4 #include "qpieseries.h"
4 #include "qpieseries.h"
5 #include <qlinechartseries.h>
5 #include <qlinechartseries.h>
6 #include <barchartseries.h>
6 #include <barchartseries.h>
7 #include <stackedbarchartseries.h>
7 #include <stackedbarchartseries.h>
8 #include <percentbarchartseries.h>
8 #include <QPushButton>
9 #include <QPushButton>
9 #include <QComboBox>
10 #include <QComboBox>
10 #include <QSpinBox>
11 #include <QSpinBox>
11 #include <QCheckBox>
12 #include <QCheckBox>
12 #include <QGridLayout>
13 #include <QGridLayout>
13 #include <QHBoxLayout>
14 #include <QHBoxLayout>
14 #include <QLabel>
15 #include <QLabel>
15 #include <QSpacerItem>
16 #include <QSpacerItem>
16 #include <QMessageBox>
17 #include <QMessageBox>
17 #include <cmath>
18 #include <cmath>
18 #include <QDebug>
19 #include <QDebug>
19 #include <QStandardItemModel>
20 #include <QStandardItemModel>
20
21
21
22
22 QTCOMMERCIALCHART_USE_NAMESPACE
23 QTCOMMERCIALCHART_USE_NAMESPACE
23
24
24 MainWidget::MainWidget(QWidget *parent) :
25 MainWidget::MainWidget(QWidget *parent) :
25 QWidget(parent)
26 QWidget(parent)
26 {
27 {
27 m_chartWidget = new QChartView(this);
28 m_chartWidget = new QChartView(this);
28 m_chartWidget->setRubberBandPolicy(QChartView::HorizonalRubberBand);
29 m_chartWidget->setRubberBandPolicy(QChartView::HorizonalRubberBand);
29
30
30 // Grid layout for the controls for configuring the chart widget
31 // Grid layout for the controls for configuring the chart widget
31 QGridLayout *grid = new QGridLayout();
32 QGridLayout *grid = new QGridLayout();
32 QPushButton *addSeriesButton = new QPushButton("Add series");
33 QPushButton *addSeriesButton = new QPushButton("Add series");
33 connect(addSeriesButton, SIGNAL(clicked()), this, SLOT(addSeries()));
34 connect(addSeriesButton, SIGNAL(clicked()), this, SLOT(addSeries()));
34 grid->addWidget(addSeriesButton, 0, 1);
35 grid->addWidget(addSeriesButton, 0, 1);
35 initBackroundCombo(grid);
36 initBackroundCombo(grid);
36 initScaleControls(grid);
37 initScaleControls(grid);
37 initThemeCombo(grid);
38 initThemeCombo(grid);
38 QCheckBox *zoomCheckBox = new QCheckBox("Drag'n drop Zoom");
39 QCheckBox *zoomCheckBox = new QCheckBox("Drag'n drop Zoom");
39 connect(zoomCheckBox, SIGNAL(toggled(bool)), m_chartWidget, SLOT(setZoomEnabled(bool)));
40 connect(zoomCheckBox, SIGNAL(toggled(bool)), m_chartWidget, SLOT(setZoomEnabled(bool)));
40 zoomCheckBox->setChecked(true);
41 zoomCheckBox->setChecked(true);
41 grid->addWidget(zoomCheckBox, grid->rowCount(), 0);
42 grid->addWidget(zoomCheckBox, grid->rowCount(), 0);
42 // add row with empty label to make all the other rows static
43 // add row with empty label to make all the other rows static
43 grid->addWidget(new QLabel(""), grid->rowCount(), 0);
44 grid->addWidget(new QLabel(""), grid->rowCount(), 0);
44 grid->setRowStretch(grid->rowCount() - 1, 1);
45 grid->setRowStretch(grid->rowCount() - 1, 1);
45
46
46 // Another grid layout as a main layout
47 // Another grid layout as a main layout
47 QGridLayout *mainLayout = new QGridLayout();
48 QGridLayout *mainLayout = new QGridLayout();
48 mainLayout->addLayout(grid, 0, 0);
49 mainLayout->addLayout(grid, 0, 0);
49
50
50 // Init series type specific controls
51 // Init series type specific controls
51 initPieControls();
52 initPieControls();
52 mainLayout->addLayout(m_pieLayout, 2, 0);
53 mainLayout->addLayout(m_pieLayout, 2, 0);
53 // Scatter series specific settings
54 // Scatter series specific settings
54 // m_scatterLayout = new QGridLayout();
55 // m_scatterLayout = new QGridLayout();
55 // m_scatterLayout->addWidget(new QLabel("scatter"), 0, 0);
56 // m_scatterLayout->addWidget(new QLabel("scatter"), 0, 0);
56 // m_scatterLayout->setEnabled(false);
57 // m_scatterLayout->setEnabled(false);
57 // mainLayout->addLayout(m_scatterLayout, 1, 0);
58 // mainLayout->addLayout(m_scatterLayout, 1, 0);
58
59
59 // Add layouts and the chart widget to the main layout
60 // Add layouts and the chart widget to the main layout
60 mainLayout->addWidget(m_chartWidget, 0, 1, 3, 1);
61 mainLayout->addWidget(m_chartWidget, 0, 1, 3, 1);
61 setLayout(mainLayout);
62 setLayout(mainLayout);
62
63
63 // force an update to test data
64 // force an update to test data
64 testDataChanged(0);
65 testDataChanged(0);
65 }
66 }
66
67
67 // Combo box for selecting the chart's background
68 // Combo box for selecting the chart's background
68 void MainWidget::initBackroundCombo(QGridLayout *grid)
69 void MainWidget::initBackroundCombo(QGridLayout *grid)
69 {
70 {
70 QComboBox *backgroundCombo = new QComboBox(this);
71 QComboBox *backgroundCombo = new QComboBox(this);
71 backgroundCombo->addItem("Color");
72 backgroundCombo->addItem("Color");
72 backgroundCombo->addItem("Gradient");
73 backgroundCombo->addItem("Gradient");
73 backgroundCombo->addItem("Image");
74 backgroundCombo->addItem("Image");
74 connect(backgroundCombo, SIGNAL(currentIndexChanged(int)),
75 connect(backgroundCombo, SIGNAL(currentIndexChanged(int)),
75 this, SLOT(backgroundChanged(int)));
76 this, SLOT(backgroundChanged(int)));
76
77
77 grid->addWidget(new QLabel("Background:"), grid->rowCount(), 0);
78 grid->addWidget(new QLabel("Background:"), grid->rowCount(), 0);
78 grid->addWidget(backgroundCombo, grid->rowCount() - 1, 1);
79 grid->addWidget(backgroundCombo, grid->rowCount() - 1, 1);
79 }
80 }
80
81
81 // Scale related controls (auto-scale vs. manual min-max values)
82 // Scale related controls (auto-scale vs. manual min-max values)
82 void MainWidget::initScaleControls(QGridLayout *grid)
83 void MainWidget::initScaleControls(QGridLayout *grid)
83 {
84 {
84 m_autoScaleCheck = new QCheckBox("Automatic scaling");
85 m_autoScaleCheck = new QCheckBox("Automatic scaling");
85 connect(m_autoScaleCheck, SIGNAL(stateChanged(int)), this, SLOT(autoScaleChanged(int)));
86 connect(m_autoScaleCheck, SIGNAL(stateChanged(int)), this, SLOT(autoScaleChanged(int)));
86 // Allow setting also non-sense values (like -2147483648 and 2147483647)
87 // Allow setting also non-sense values (like -2147483648 and 2147483647)
87 m_xMinSpin = new QSpinBox();
88 m_xMinSpin = new QSpinBox();
88 m_xMinSpin->setMinimum(INT_MIN);
89 m_xMinSpin->setMinimum(INT_MIN);
89 m_xMinSpin->setMaximum(INT_MAX);
90 m_xMinSpin->setMaximum(INT_MAX);
90 m_xMinSpin->setValue(0);
91 m_xMinSpin->setValue(0);
91 connect(m_xMinSpin, SIGNAL(valueChanged(int)), this, SLOT(xMinChanged(int)));
92 connect(m_xMinSpin, SIGNAL(valueChanged(int)), this, SLOT(xMinChanged(int)));
92 m_xMaxSpin = new QSpinBox();
93 m_xMaxSpin = new QSpinBox();
93 m_xMaxSpin->setMinimum(INT_MIN);
94 m_xMaxSpin->setMinimum(INT_MIN);
94 m_xMaxSpin->setMaximum(INT_MAX);
95 m_xMaxSpin->setMaximum(INT_MAX);
95 m_xMaxSpin->setValue(10);
96 m_xMaxSpin->setValue(10);
96 connect(m_xMaxSpin, SIGNAL(valueChanged(int)), this, SLOT(xMaxChanged(int)));
97 connect(m_xMaxSpin, SIGNAL(valueChanged(int)), this, SLOT(xMaxChanged(int)));
97 m_yMinSpin = new QSpinBox();
98 m_yMinSpin = new QSpinBox();
98 m_yMinSpin->setMinimum(INT_MIN);
99 m_yMinSpin->setMinimum(INT_MIN);
99 m_yMinSpin->setMaximum(INT_MAX);
100 m_yMinSpin->setMaximum(INT_MAX);
100 m_yMinSpin->setValue(0);
101 m_yMinSpin->setValue(0);
101 connect(m_yMinSpin, SIGNAL(valueChanged(int)), this, SLOT(yMinChanged(int)));
102 connect(m_yMinSpin, SIGNAL(valueChanged(int)), this, SLOT(yMinChanged(int)));
102 m_yMaxSpin = new QSpinBox();
103 m_yMaxSpin = new QSpinBox();
103 m_yMaxSpin->setMinimum(INT_MIN);
104 m_yMaxSpin->setMinimum(INT_MIN);
104 m_yMaxSpin->setMaximum(INT_MAX);
105 m_yMaxSpin->setMaximum(INT_MAX);
105 m_yMaxSpin->setValue(10);
106 m_yMaxSpin->setValue(10);
106 connect(m_yMaxSpin, SIGNAL(valueChanged(int)), this, SLOT(yMaxChanged(int)));
107 connect(m_yMaxSpin, SIGNAL(valueChanged(int)), this, SLOT(yMaxChanged(int)));
107
108
108 grid->addWidget(m_autoScaleCheck, grid->rowCount(), 0);
109 grid->addWidget(m_autoScaleCheck, grid->rowCount(), 0);
109 grid->addWidget(new QLabel("x min:"), grid->rowCount(), 0);
110 grid->addWidget(new QLabel("x min:"), grid->rowCount(), 0);
110 grid->addWidget(m_xMinSpin, grid->rowCount() - 1, 1);
111 grid->addWidget(m_xMinSpin, grid->rowCount() - 1, 1);
111 grid->addWidget(new QLabel("x max:"), grid->rowCount(), 0);
112 grid->addWidget(new QLabel("x max:"), grid->rowCount(), 0);
112 grid->addWidget(m_xMaxSpin, grid->rowCount() - 1, 1);
113 grid->addWidget(m_xMaxSpin, grid->rowCount() - 1, 1);
113 grid->addWidget(new QLabel("y min:"), grid->rowCount(), 0);
114 grid->addWidget(new QLabel("y min:"), grid->rowCount(), 0);
114 grid->addWidget(m_yMinSpin, grid->rowCount() - 1, 1);
115 grid->addWidget(m_yMinSpin, grid->rowCount() - 1, 1);
115 grid->addWidget(new QLabel("y max:"), grid->rowCount(), 0);
116 grid->addWidget(new QLabel("y max:"), grid->rowCount(), 0);
116 grid->addWidget(m_yMaxSpin, grid->rowCount() - 1, 1);
117 grid->addWidget(m_yMaxSpin, grid->rowCount() - 1, 1);
117
118
118 m_autoScaleCheck->setChecked(true);
119 m_autoScaleCheck->setChecked(true);
119 }
120 }
120
121
121 // Combo box for selecting theme
122 // Combo box for selecting theme
122 void MainWidget::initThemeCombo(QGridLayout *grid)
123 void MainWidget::initThemeCombo(QGridLayout *grid)
123 {
124 {
124 QComboBox *chartTheme = new QComboBox();
125 QComboBox *chartTheme = new QComboBox();
125 chartTheme->addItem("Default");
126 chartTheme->addItem("Default");
126 chartTheme->addItem("Vanilla");
127 chartTheme->addItem("Vanilla");
127 chartTheme->addItem("Icy");
128 chartTheme->addItem("Icy");
128 chartTheme->addItem("Grayscale");
129 chartTheme->addItem("Grayscale");
129 chartTheme->addItem("Scientific");
130 chartTheme->addItem("Scientific");
130 chartTheme->addItem("Unnamed1");
131 chartTheme->addItem("Unnamed1");
131 connect(chartTheme, SIGNAL(currentIndexChanged(int)),
132 connect(chartTheme, SIGNAL(currentIndexChanged(int)),
132 this, SLOT(changeChartTheme(int)));
133 this, SLOT(changeChartTheme(int)));
133 grid->addWidget(new QLabel("Chart theme:"), 8, 0);
134 grid->addWidget(new QLabel("Chart theme:"), 8, 0);
134 grid->addWidget(chartTheme, 8, 1);
135 grid->addWidget(chartTheme, 8, 1);
135 }
136 }
136
137
137 void MainWidget::initPieControls()
138 void MainWidget::initPieControls()
138 {
139 {
139 // Pie series specific settings
140 // Pie series specific settings
140 // Pie size factory
141 // Pie size factory
141 QDoubleSpinBox *pieSizeSpin = new QDoubleSpinBox();
142 QDoubleSpinBox *pieSizeSpin = new QDoubleSpinBox();
142 pieSizeSpin->setMinimum(LONG_MIN);
143 pieSizeSpin->setMinimum(LONG_MIN);
143 pieSizeSpin->setMaximum(LONG_MAX);
144 pieSizeSpin->setMaximum(LONG_MAX);
144 pieSizeSpin->setValue(1.0);
145 pieSizeSpin->setValue(1.0);
145 pieSizeSpin->setSingleStep(0.1);
146 pieSizeSpin->setSingleStep(0.1);
146 connect(pieSizeSpin, SIGNAL(valueChanged(double)), this, SLOT(setPieSizeFactor(double)));
147 connect(pieSizeSpin, SIGNAL(valueChanged(double)), this, SLOT(setPieSizeFactor(double)));
147 // Pie position
148 // Pie position
148 QComboBox *piePosCombo = new QComboBox(this);
149 QComboBox *piePosCombo = new QComboBox(this);
149 piePosCombo->addItem("Maximized");
150 piePosCombo->addItem("Maximized");
150 piePosCombo->addItem("Top left");
151 piePosCombo->addItem("Top left");
151 piePosCombo->addItem("Top right");
152 piePosCombo->addItem("Top right");
152 piePosCombo->addItem("Bottom left");
153 piePosCombo->addItem("Bottom left");
153 piePosCombo->addItem("Bottom right");
154 piePosCombo->addItem("Bottom right");
154 connect(piePosCombo, SIGNAL(currentIndexChanged(int)),
155 connect(piePosCombo, SIGNAL(currentIndexChanged(int)),
155 this, SLOT(setPiePosition(int)));
156 this, SLOT(setPiePosition(int)));
156 m_pieLayout = new QGridLayout();
157 m_pieLayout = new QGridLayout();
157 m_pieLayout->setEnabled(false);
158 m_pieLayout->setEnabled(false);
158 m_pieLayout->addWidget(new QLabel("Pie size factor"), 0, 0);
159 m_pieLayout->addWidget(new QLabel("Pie size factor"), 0, 0);
159 m_pieLayout->addWidget(pieSizeSpin, 0, 1);
160 m_pieLayout->addWidget(pieSizeSpin, 0, 1);
160 m_pieLayout->addWidget(new QLabel("Pie position"), 1, 0);
161 m_pieLayout->addWidget(new QLabel("Pie position"), 1, 0);
161 m_pieLayout->addWidget(piePosCombo, 1, 1);
162 m_pieLayout->addWidget(piePosCombo, 1, 1);
162 }
163 }
163
164
164 void MainWidget::addSeries()
165 void MainWidget::addSeries()
165 {
166 {
166 DataSerieDialog dialog(m_defaultSeriesName, this);
167 DataSerieDialog dialog(m_defaultSeriesName, this);
167 connect(&dialog, SIGNAL(accepted(QString, QString)), this, SLOT(addSeries(QString, QString)));
168 connect(&dialog, SIGNAL(accepted(QString, QString)), this, SLOT(addSeries(QString, QString)));
168 dialog.exec();
169 dialog.exec();
169 }
170 }
170
171
171 void MainWidget::addSeries(QString series, QString data)
172 void MainWidget::addSeries(QString series, QString data)
172 {
173 {
173 qDebug() << "addSeries: " << series << " data: " << data;
174 qDebug() << "addSeries: " << series << " data: " << data;
174 m_defaultSeriesName = series;
175 m_defaultSeriesName = series;
175
176
176 // TODO: a dedicated data class for storing x and y values
177 // TODO: a dedicated data class for storing x and y values
177 QList<qreal> x;
178 QList<qreal> x;
178 QList<qreal> y;
179 QList<qreal> y;
179
180
181 QList<qreal> data0;
182 QList<qreal> data1;
183 QList<qreal> data2;
184 QList<qreal> data3;
185 QList<qreal> data4;
186
180 if (data == "linear") {
187 if (data == "linear") {
181 for (int i = 0; i < 20; i++) {
188 for (int i = 0; i < 20; i++) {
182 x.append(i);
189 x.append(i);
183 y.append(i);
190 y.append(i);
184 }
191 }
185 } else if (data == "linear, 1M") {
192 } else if (data == "linear, 1M") {
186 // 1 million data points from 0.0001 to 100
193 // 1 million data points from 0.0001 to 100
187 // TODO: What is the requirement? Should we be able to show this kind of data with
194 // TODO: What is the requirement? Should we be able to show this kind of data with
188 // reasonable performance, or can we expect the application developer to do "data mining"
195 // reasonable performance, or can we expect the application developer to do "data mining"
189 // for us, so that the count of data points given to QtCommercial Chart is always
196 // for us, so that the count of data points given to QtCommercial Chart is always
190 // reasonable?
197 // reasonable?
191 for (qreal i = 0; i < 100; i += 0.0001) {
198 for (qreal i = 0; i < 100; i += 0.0001) {
192 x.append(i);
199 x.append(i);
193 y.append(20);
200 y.append(20);
194 }
201 }
195 } else if (data == "SIN") {
202 } else if (data == "SIN") {
196 for (int i = 0; i < 100; i++) {
203 for (int i = 0; i < 100; i++) {
197 x.append(i);
204 x.append(i);
198 y.append(abs(sin(3.14159265358979 / 50 * i) * 100));
205 y.append(abs(sin(3.14159265358979 / 50 * i) * 100));
199 }
206 }
200 } else if (data == "SIN + random") {
207 } else if (data == "SIN + random") {
201 for (qreal i = 0; i < 100; i += 0.1) {
208 for (qreal i = 0; i < 100; i += 0.1) {
202 x.append(i + (rand() % 5));
209 x.append(i + (rand() % 5));
203 y.append(abs(sin(3.14159265358979 / 50 * i) * 100) + (rand() % 5));
210 y.append(abs(sin(3.14159265358979 / 50 * i) * 100) + (rand() % 5));
204 }
211 }
212 } else if (data == "Table, 5 series"){
213 // Create some test data to chart
214 data0 << 1 << 2 << 3 << 4 << 5 << 6 << 7 << 8 << 9 << 10;
215 data1 << 5 << 0 << 0 << 4 << 0 << 7 << 8 << 9 << 9 << 0;
216 data2 << 3 << 5 << 8 << 13 << 8 << 5 << 3 << 2 << 1 << 1;
217 data3 << 5 << 6 << 7 << 3 << 4 << 5 << 8 << 9 << 10 << 5;
218 data4 << 9 << 7 << 5 << 3 << 1 << 2 << 4 << 6 << 8 << 10;
205 } else {
219 } else {
206 // TODO: check if data has a valid file name
220 // TODO: check if data has a valid file name
207 Q_ASSERT(false);
221 Q_ASSERT(false);
208 }
222 }
209
223
210 // TODO: color of the series
224 // TODO: color of the series
211 QChartSeries *newSeries = 0;
225 QChartSeries *newSeries = 0;
212 if (series == "Scatter") {
226 if (series == "Scatter") {
213 newSeries = m_chartWidget->createSeries(QChartSeries::SeriesTypeScatter);
227 newSeries = m_chartWidget->createSeries(QChartSeries::SeriesTypeScatter);
214 Q_ASSERT(newSeries->setData(x, y));
228 Q_ASSERT(newSeries->setData(x, y));
215 } else if (series == "Pie") {
229 } else if (series == "Pie") {
216 newSeries = m_chartWidget->createSeries(QChartSeries::SeriesTypePie);
230 newSeries = m_chartWidget->createSeries(QChartSeries::SeriesTypePie);
217 Q_ASSERT(newSeries->setData(y));
231 Q_ASSERT(newSeries->setData(y));
218 } else if (series == "Line") {
232 } else if (series == "Line") {
219 // TODO: adding data to an existing line series does not give any visuals for some reason
233 // TODO: adding data to an existing line series does not give any visuals for some reason
220 // newSeries = m_chartWidget->createSeries(QChartSeries::SeriesTypeLine);
234 // newSeries = m_chartWidget->createSeries(QChartSeries::SeriesTypeLine);
221 // QXYChartSeries *lineSeries = static_cast<QXYChartSeries *>(newSeries);
235 // QXYChartSeries *lineSeries = static_cast<QXYChartSeries *>(newSeries);
222 // lineSeries->setColor(Qt::blue);
236 // lineSeries->setColor(Qt::blue);
223 // for (int i(0); i < x.count() && i < y.count(); i++) {
237 // for (int i(0); i < x.count() && i < y.count(); i++) {
224 // lineSeries->add(x.at(i), y.at(i));
238 // lineSeries->add(x.at(i), y.at(i));
225 // }
239 // }
226 //Q_ASSERT(newSeries->setData(x, y));
240 //Q_ASSERT(newSeries->setData(x, y));
227 QLineChartSeries* series0 = new QLineChartSeries();
241 QLineChartSeries* series0 = new QLineChartSeries();
228 for (int i(0); i < x.count() && i < y.count(); i++)
242 for (int i(0); i < x.count() && i < y.count(); i++)
229 series0->add(x.at(i), y.at(i));
243 series0->add(x.at(i), y.at(i));
230 m_chartWidget->addSeries(series0);
244 m_chartWidget->addSeries(series0);
231 newSeries = series0;
245 newSeries = series0;
232 } else {
246 } else if (series == "Bar") {
233 // TODO
247 qDebug() << "Bar chart series";
234 }
248 BarChartSeries* series0 = new BarChartSeries(this);
235
249 series0->addData(data0);
236 // BarChart
250 series0->addData(data1);
237 if (series == "Bar") {
251 series0->addData(data2);
238 // This is the another way of creating series. Should we create test cases for both ways, if we support them?
252 series0->addData(data3);
253 series0->addData(data4);
254 m_chartWidget->addSeries(series0);
255 newSeries = series0;
256 } else if (series == "StackedBar") {
239 qDebug() << "Bar chart series";
257 qDebug() << "Bar chart series";
240 StackedBarChartSeries* series0 = new StackedBarChartSeries(this);
258 StackedBarChartSeries* series0 = new StackedBarChartSeries(this);
241
242 // Create some test data to chart
243 QList<qreal> data0;
244 data0 << 1 << 2 << 3 << 4 << 5 << 6 << 7 << 8 << 9 << 10;
245 QList<qreal> data1;
246 data1 << 5 << 0 << 0 << 4 << 0 << 7 << 8 << 9 << 9 << 0;
247 QList<qreal> data2;
248 data2 << 3 << 5 << 8 << 13 << 8 << 5 << 3 << 2 << 1 << 1;
249 QList<qreal> data3;
250 data3 << 5 << 6 << 7 << 3 << 4 << 5 << 8 << 9 << 10 << 5;
251 QList<qreal> data4;
252 data4 << 9 << 7 << 5 << 3 << 1 << 2 << 4 << 6 << 8 << 10;
253
254 series0->addData(data0);
259 series0->addData(data0);
255 series0->addData(data1);
260 series0->addData(data1);
256 series0->addData(data2);
261 series0->addData(data2);
257 series0->addData(data3);
262 series0->addData(data3);
258 series0->addData(data4);
263 series0->addData(data4);
259
260 m_chartWidget->addSeries(series0);
264 m_chartWidget->addSeries(series0);
261 newSeries = series0;
265 newSeries = series0;
266 } else if (series == "PercentBar") {
267 qDebug() << "Bar chart series";
268 PercentBarChartSeries* series0 = new PercentBarChartSeries(this);
269 series0->addData(data0);
270 series0->addData(data1);
271 series0->addData(data2);
272 series0->addData(data3);
273 series0->addData(data4);
274 m_chartWidget->addSeries(series0);
275 newSeries = series0;
276 } else {
277 qDebug() << "Something weird going on in MainWidget::addSeries";
262 }
278 }
263
279
264 setCurrentSeries(newSeries);
280 setCurrentSeries(newSeries);
265 }
281 }
266
282
267 void MainWidget::setCurrentSeries(QChartSeries *series)
283 void MainWidget::setCurrentSeries(QChartSeries *series)
268 {
284 {
269 m_currentSeries = series;
285 m_currentSeries = series;
270 switch (m_currentSeries->type()) {
286 switch (m_currentSeries->type()) {
271 case QChartSeries::SeriesTypeLine:
287 case QChartSeries::SeriesTypeLine:
272 break;
288 break;
273 case QChartSeries::SeriesTypeScatter:
289 case QChartSeries::SeriesTypeScatter:
274 break;
290 break;
275 case QChartSeries::SeriesTypePie:
291 case QChartSeries::SeriesTypePie:
276 break;
292 break;
277 case QChartSeries::SeriesTypeBar:
293 case QChartSeries::SeriesTypeBar:
278 qDebug() << "setCurrentSeries (bar)";
294 qDebug() << "setCurrentSeries (bar)";
279 break;
295 break;
296 case QChartSeries::SeriesTypeStackedBar:
297 qDebug() << "setCurrentSeries (Stackedbar)";
298 break;
299 case QChartSeries::SeriesTypePercentBar:
300 qDebug() << "setCurrentSeries (Percentbar)";
301 break;
280 default:
302 default:
281 Q_ASSERT(false);
303 Q_ASSERT(false);
282 break;
304 break;
283 }
305 }
284 }
306 }
285
307
286 void MainWidget::testDataChanged(int itemIndex)
308 void MainWidget::testDataChanged(int itemIndex)
287 {
309 {
288 qDebug() << "testDataChanged: " << itemIndex;
310 qDebug() << "testDataChanged: " << itemIndex;
289
311
290 // switch (itemIndex) {
312 // switch (itemIndex) {
291 // case 0: {
313 // case 0: {
292 // QList<QChartDataPoint> data;
314 // QList<QChartDataPoint> data;
293 // for (int x = 0; x < 20; x++) {
315 // for (int x = 0; x < 20; x++) {
294 // data.append(QChartDataPoint() << x << x / 2);
316 // data.append(QChartDataPoint() << x << x / 2);
295 // }
317 // }
296 // m_chartWidget->setData(data);
318 // m_chartWidget->setData(data);
297 // break;
319 // break;
298 // }
320 // }
299 // case 1: {
321 // case 1: {
300 // QList<QChartDataPoint> data;
322 // QList<QChartDataPoint> data;
301 // for (int x = 0; x < 100; x++) {
323 // for (int x = 0; x < 100; x++) {
302 // data.append(QChartDataPoint() << x - 200 << 2 * (uint(sin(3.14159/50*x)*80) % 100));
324 // data.append(QChartDataPoint() << x - 200 << 2 * (uint(sin(3.14159/50*x)*80) % 100));
303 // }
325 // }
304 // m_chartWidget->setData(data);
326 // m_chartWidget->setData(data);
305 // break;
327 // break;
306 // }
328 // }
307 // case 2: {
329 // case 2: {
308 // QList<QChartDataPoint> data;
330 // QList<QChartDataPoint> data;
309 // for (int x = 0; x < 1000; x++) {
331 // for (int x = 0; x < 1000; x++) {
310 // data.append(QChartDataPoint() << x - 200 << 2 * (uint(sin(3.14159/50*x)*80) % 100) + (rand() % 100 * 0.2));
332 // data.append(QChartDataPoint() << x - 200 << 2 * (uint(sin(3.14159/50*x)*80) % 100) + (rand() % 100 * 0.2));
311 // data.append(QChartDataPoint() << x - 200 << 2 * (uint(sin(3.14159/50*x)*80) % 100) + (rand() % 100 * 0.2));
333 // data.append(QChartDataPoint() << x - 200 << 2 * (uint(sin(3.14159/50*x)*80) % 100) + (rand() % 100 * 0.2));
312 // data.append(QChartDataPoint() << x - 200 << 2 * (uint(sin(3.14159/50*x)*80) % 100) + (rand() % 100 * 0.2));
334 // data.append(QChartDataPoint() << x - 200 << 2 * (uint(sin(3.14159/50*x)*80) % 100) + (rand() % 100 * 0.2));
313 // }
335 // }
314 // m_chartWidget->setData(data);
336 // m_chartWidget->setData(data);
315 // break;
337 // break;
316 // }
338 // }
317 // default:
339 // default:
318 // break;
340 // break;
319 // }
341 // }
320 }
342 }
321
343
322 void MainWidget::backgroundChanged(int itemIndex)
344 void MainWidget::backgroundChanged(int itemIndex)
323 {
345 {
324 qDebug() << "backgroundChanged: " << itemIndex;
346 qDebug() << "backgroundChanged: " << itemIndex;
325 }
347 }
326
348
327 void MainWidget::autoScaleChanged(int value)
349 void MainWidget::autoScaleChanged(int value)
328 {
350 {
329 if (value) {
351 if (value) {
330 // TODO: enable auto scaling
352 // TODO: enable auto scaling
331 } else {
353 } else {
332 // TODO: set scaling manually (and disable auto scaling)
354 // TODO: set scaling manually (and disable auto scaling)
333 }
355 }
334
356
335 m_xMinSpin->setEnabled(!value);
357 m_xMinSpin->setEnabled(!value);
336 m_xMaxSpin->setEnabled(!value);
358 m_xMaxSpin->setEnabled(!value);
337 m_yMinSpin->setEnabled(!value);
359 m_yMinSpin->setEnabled(!value);
338 m_yMaxSpin->setEnabled(!value);
360 m_yMaxSpin->setEnabled(!value);
339 }
361 }
340
362
341 void MainWidget::xMinChanged(int value)
363 void MainWidget::xMinChanged(int value)
342 {
364 {
343 qDebug() << "xMinChanged: " << value;
365 qDebug() << "xMinChanged: " << value;
344 }
366 }
345
367
346 void MainWidget::xMaxChanged(int value)
368 void MainWidget::xMaxChanged(int value)
347 {
369 {
348 qDebug() << "xMaxChanged: " << value;
370 qDebug() << "xMaxChanged: " << value;
349 }
371 }
350
372
351 void MainWidget::yMinChanged(int value)
373 void MainWidget::yMinChanged(int value)
352 {
374 {
353 qDebug() << "yMinChanged: " << value;
375 qDebug() << "yMinChanged: " << value;
354 }
376 }
355
377
356 void MainWidget::yMaxChanged(int value)
378 void MainWidget::yMaxChanged(int value)
357 {
379 {
358 qDebug() << "yMaxChanged: " << value;
380 qDebug() << "yMaxChanged: " << value;
359 }
381 }
360
382
361 void MainWidget::changeChartTheme(int themeIndex)
383 void MainWidget::changeChartTheme(int themeIndex)
362 {
384 {
363 qDebug() << "changeChartTheme: " << themeIndex;
385 qDebug() << "changeChartTheme: " << themeIndex;
364 m_chartWidget->setChartTheme((QChart::ChartTheme) themeIndex);
386 m_chartWidget->setChartTheme((QChart::ChartTheme) themeIndex);
365 }
387 }
366
388
367 void MainWidget::setPieSizeFactor(double size)
389 void MainWidget::setPieSizeFactor(double size)
368 {
390 {
369 QPieSeries *pie = qobject_cast<QPieSeries *>(m_currentSeries);
391 QPieSeries *pie = qobject_cast<QPieSeries *>(m_currentSeries);
370 if (pie)
392 if (pie)
371 pie->setSizeFactor(qreal(size));
393 pie->setSizeFactor(qreal(size));
372 }
394 }
373
395
374 void MainWidget::setPiePosition(int position)
396 void MainWidget::setPiePosition(int position)
375 {
397 {
376 QPieSeries *pie = qobject_cast<QPieSeries *>(m_currentSeries);
398 QPieSeries *pie = qobject_cast<QPieSeries *>(m_currentSeries);
377 if (pie)
399 if (pie)
378 pie->setPosition((QPieSeries::PiePosition) position);
400 pie->setPosition((QPieSeries::PiePosition) position);
379 }
401 }
General Comments 0
You need to be logged in to leave comments. Login now