@@ -0,0 +1,6 | |||||
|
1 | #include "chartwidget.h" | |||
|
2 | ||||
|
3 | ChartWidget::ChartWidget(QWidget *parent) : | |||
|
4 | QChartView(parent) | |||
|
5 | { | |||
|
6 | } |
@@ -0,0 +1,21 | |||||
|
1 | #ifndef CHARTWIDGET_H | |||
|
2 | #define CHARTWIDGET_H | |||
|
3 | ||||
|
4 | #include <qchartview.h> | |||
|
5 | ||||
|
6 | QTCOMMERCIALCHART_USE_NAMESPACE | |||
|
7 | ||||
|
8 | ||||
|
9 | class ChartWidget : public QChartView | |||
|
10 | { | |||
|
11 | Q_OBJECT | |||
|
12 | public: | |||
|
13 | explicit ChartWidget(QWidget *parent = 0); | |||
|
14 | ||||
|
15 | signals: | |||
|
16 | ||||
|
17 | public slots: | |||
|
18 | ||||
|
19 | }; | |||
|
20 | ||||
|
21 | #endif // CHARTWIDGET_H |
@@ -0,0 +1,88 | |||||
|
1 | #include <QApplication> | |||
|
2 | #include <QMainWindow> | |||
|
3 | #include <QStandardItemModel> | |||
|
4 | #include <stackedbarchartseries.h> | |||
|
5 | #include "chartwidget.h" | |||
|
6 | ||||
|
7 | QTCOMMERCIALCHART_USE_NAMESPACE | |||
|
8 | ||||
|
9 | int main(int argc, char *argv[]) | |||
|
10 | { | |||
|
11 | QApplication a(argc, argv); | |||
|
12 | QMainWindow window; | |||
|
13 | ||||
|
14 | StackedBarChartSeries* series0 = new StackedBarChartSeries(); | |||
|
15 | ||||
|
16 | // Create some test data to chart | |||
|
17 | QStandardItemModel dataModel(5,10); | |||
|
18 | QModelIndex index; | |||
|
19 | index = dataModel.index(0,0); | |||
|
20 | ||||
|
21 | // Series 0 | |||
|
22 | dataModel.setData(dataModel.index(0,0),1); | |||
|
23 | dataModel.setData(dataModel.index(0,1),2); | |||
|
24 | dataModel.setData(dataModel.index(0,2),3); | |||
|
25 | dataModel.setData(dataModel.index(0,3),4); | |||
|
26 | dataModel.setData(dataModel.index(0,4),5); | |||
|
27 | dataModel.setData(dataModel.index(0,5),6); | |||
|
28 | dataModel.setData(dataModel.index(0,6),7); | |||
|
29 | dataModel.setData(dataModel.index(0,7),8); | |||
|
30 | dataModel.setData(dataModel.index(0,8),9); | |||
|
31 | dataModel.setData(dataModel.index(0,9),10); | |||
|
32 | ||||
|
33 | // Series 1, some other items missing | |||
|
34 | dataModel.setData(dataModel.index(1,0),5); | |||
|
35 | dataModel.setData(dataModel.index(1,3),4); | |||
|
36 | dataModel.setData(dataModel.index(1,5),7); | |||
|
37 | dataModel.setData(dataModel.index(1,6),8); | |||
|
38 | dataModel.setData(dataModel.index(1,8),9); | |||
|
39 | dataModel.setData(dataModel.index(1,9),9); | |||
|
40 | ||||
|
41 | // Series 2 | |||
|
42 | dataModel.setData(dataModel.index(2,0),3); | |||
|
43 | dataModel.setData(dataModel.index(2,1),5); | |||
|
44 | dataModel.setData(dataModel.index(2,2),8); | |||
|
45 | dataModel.setData(dataModel.index(2,3),13); | |||
|
46 | dataModel.setData(dataModel.index(2,4),8); | |||
|
47 | dataModel.setData(dataModel.index(2,5),5); | |||
|
48 | dataModel.setData(dataModel.index(2,6),3); | |||
|
49 | dataModel.setData(dataModel.index(2,7),2); | |||
|
50 | dataModel.setData(dataModel.index(2,8),1); | |||
|
51 | dataModel.setData(dataModel.index(2,9),1); | |||
|
52 | ||||
|
53 | // Series 3 | |||
|
54 | dataModel.setData(dataModel.index(3,0),5); | |||
|
55 | dataModel.setData(dataModel.index(3,1),6); | |||
|
56 | dataModel.setData(dataModel.index(3,2),7); | |||
|
57 | dataModel.setData(dataModel.index(3,3),3); | |||
|
58 | dataModel.setData(dataModel.index(3,4),4); | |||
|
59 | dataModel.setData(dataModel.index(3,5),5); | |||
|
60 | dataModel.setData(dataModel.index(3,6),8); | |||
|
61 | dataModel.setData(dataModel.index(3,7),9); | |||
|
62 | dataModel.setData(dataModel.index(3,8),10); | |||
|
63 | dataModel.setData(dataModel.index(3,9),5); | |||
|
64 | ||||
|
65 | // Series 4 | |||
|
66 | dataModel.setData(dataModel.index(4,0),9); | |||
|
67 | dataModel.setData(dataModel.index(4,1),7); | |||
|
68 | dataModel.setData(dataModel.index(4,2),5); | |||
|
69 | dataModel.setData(dataModel.index(4,3),3); | |||
|
70 | dataModel.setData(dataModel.index(4,4),1); | |||
|
71 | dataModel.setData(dataModel.index(4,5),2); | |||
|
72 | dataModel.setData(dataModel.index(4,6),4); | |||
|
73 | dataModel.setData(dataModel.index(4,7),6); | |||
|
74 | dataModel.setData(dataModel.index(4,8),8); | |||
|
75 | dataModel.setData(dataModel.index(4,9),10); | |||
|
76 | ||||
|
77 | series0->setData(&dataModel); | |||
|
78 | ||||
|
79 | ChartWidget* chartWidget = new ChartWidget(&window); | |||
|
80 | chartWidget->addSeries(series0); | |||
|
81 | ||||
|
82 | window.setCentralWidget(chartWidget); | |||
|
83 | window.resize(400, 300); | |||
|
84 | window.show(); | |||
|
85 | ||||
|
86 | return a.exec(); | |||
|
87 | } | |||
|
88 |
@@ -0,0 +1,17 | |||||
|
1 | !include( ../../common.pri ) { | |||
|
2 | error( "Couldn't find the common.pri file!" ) | |||
|
3 | } | |||
|
4 | ||||
|
5 | !include( ../../integrated.pri ) { | |||
|
6 | error( "Couldn't find the integrated.pri file !") | |||
|
7 | } | |||
|
8 | ||||
|
9 | TARGET = stackedbarchart | |||
|
10 | TEMPLATE = app | |||
|
11 | QT += core gui | |||
|
12 | SOURCES += main.cpp \ | |||
|
13 | chartwidget.cpp | |||
|
14 | ||||
|
15 | HEADERS += \ | |||
|
16 | chartwidget.h | |||
|
17 |
@@ -0,0 +1,107 | |||||
|
1 | #include <limits.h> | |||
|
2 | #include "stackedbarchartseries.h" | |||
|
3 | ||||
|
4 | QTCOMMERCIALCHART_BEGIN_NAMESPACE | |||
|
5 | ||||
|
6 | StackedBarChartSeries::StackedBarChartSeries(QObject *parent) : | |||
|
7 | QChartSeries(parent) | |||
|
8 | { | |||
|
9 | } | |||
|
10 | ||||
|
11 | bool StackedBarChartSeries::setData(QAbstractItemModel* model) | |||
|
12 | { | |||
|
13 | mModel = model; | |||
|
14 | } | |||
|
15 | ||||
|
16 | int StackedBarChartSeries::min() | |||
|
17 | { | |||
|
18 | Q_ASSERT(mModel->rowCount() > 0); | |||
|
19 | Q_ASSERT(mModel->columnCount() > 0); | |||
|
20 | ||||
|
21 | // TODO: make min and max members and update them when data changes. | |||
|
22 | // This is slower since they are checked every time, even if data is same since previous call. | |||
|
23 | int min = INT_MAX; | |||
|
24 | ||||
|
25 | for (int i=0; i <mModel->rowCount(); i++) { | |||
|
26 | for(int j=0; j<mModel->columnCount(); j++) { | |||
|
27 | int temp = mModel->data(mModel->index(i,j)).toInt(); | |||
|
28 | if (temp < min) { | |||
|
29 | min = temp; | |||
|
30 | } | |||
|
31 | } | |||
|
32 | } | |||
|
33 | return min; | |||
|
34 | } | |||
|
35 | ||||
|
36 | int StackedBarChartSeries::max() | |||
|
37 | { | |||
|
38 | Q_ASSERT(mModel->rowCount() > 0); | |||
|
39 | Q_ASSERT(mModel->columnCount() > 0); | |||
|
40 | ||||
|
41 | // TODO: make min and max members and update them when data changes. | |||
|
42 | // This is slower since they are checked every time, even if data is same since previous call. | |||
|
43 | int max = INT_MIN; | |||
|
44 | ||||
|
45 | for (int i=0; i <mModel->rowCount(); i++) { | |||
|
46 | for(int j=0; j<mModel->columnCount(); j++) { | |||
|
47 | int temp = mModel->data(mModel->index(i,j)).toInt(); | |||
|
48 | if (temp > max) { | |||
|
49 | max = temp; | |||
|
50 | } | |||
|
51 | } | |||
|
52 | } | |||
|
53 | return max; | |||
|
54 | } | |||
|
55 | ||||
|
56 | int StackedBarChartSeries::maxColumnSum() | |||
|
57 | { | |||
|
58 | Q_ASSERT(mModel->rowCount() > 0); | |||
|
59 | Q_ASSERT(mModel->columnCount() > 0); | |||
|
60 | ||||
|
61 | int max = INT_MIN; | |||
|
62 | ||||
|
63 | for (int col=0; col <mModel->rowCount(); col++) { | |||
|
64 | int sum = columnSum(col); | |||
|
65 | if (sum > max) { | |||
|
66 | max = sum; | |||
|
67 | } | |||
|
68 | } | |||
|
69 | return max; | |||
|
70 | } | |||
|
71 | ||||
|
72 | int StackedBarChartSeries::countRows() | |||
|
73 | { | |||
|
74 | return mModel->rowCount(); | |||
|
75 | } | |||
|
76 | ||||
|
77 | int StackedBarChartSeries::countColumns() | |||
|
78 | { | |||
|
79 | return mModel->columnCount(); | |||
|
80 | } | |||
|
81 | ||||
|
82 | int StackedBarChartSeries::countTotalItems() | |||
|
83 | { | |||
|
84 | return mModel->rowCount() * mModel->columnCount(); | |||
|
85 | } | |||
|
86 | ||||
|
87 | int StackedBarChartSeries::valueAt(int row, int column) | |||
|
88 | { | |||
|
89 | QModelIndex index = mModel->index(row,column); | |||
|
90 | return mModel->data(index).toInt(); | |||
|
91 | } | |||
|
92 | ||||
|
93 | int StackedBarChartSeries::columnSum(int column) | |||
|
94 | { | |||
|
95 | int sum(0); | |||
|
96 | int count = mModel->rowCount(); | |||
|
97 | ||||
|
98 | for (int row = 0; row < count; row++) { | |||
|
99 | sum += mModel->data(mModel->index(row,column)).toInt(); | |||
|
100 | } | |||
|
101 | return sum; | |||
|
102 | } | |||
|
103 | ||||
|
104 | #include "moc_stackedbarchartseries.cpp" | |||
|
105 | ||||
|
106 | QTCOMMERCIALCHART_END_NAMESPACE | |||
|
107 |
@@ -0,0 +1,47 | |||||
|
1 | #ifndef STACKEDBARCHARTSERIES_H | |||
|
2 | #define STACKEDBARCHARTSERIES_H | |||
|
3 | ||||
|
4 | #include <QList> | |||
|
5 | #include <QAbstractItemModel> | |||
|
6 | #include "qchartseries.h" | |||
|
7 | ||||
|
8 | QTCOMMERCIALCHART_BEGIN_NAMESPACE | |||
|
9 | ||||
|
10 | class StackedBarGroup; | |||
|
11 | ||||
|
12 | class QTCOMMERCIALCHART_EXPORT StackedBarChartSeries : public QChartSeries | |||
|
13 | { | |||
|
14 | Q_OBJECT | |||
|
15 | public: | |||
|
16 | StackedBarChartSeries(QObject* parent=0); | |||
|
17 | ||||
|
18 | // from QChartSeries | |||
|
19 | virtual QChartSeriesType type() const { return QChartSeries::SeriesTypeStackedBar; } | |||
|
20 | ||||
|
21 | // TODO: Better data model? | |||
|
22 | virtual bool setData(QAbstractItemModel* model); | |||
|
23 | ||||
|
24 | // Methods to find out minimum and maximum values of data | |||
|
25 | int min(); | |||
|
26 | int max(); | |||
|
27 | int maxColumnSum(); // returns maximum sum of items in all columns. | |||
|
28 | ||||
|
29 | int countRows(); | |||
|
30 | int countColumns(); | |||
|
31 | int countTotalItems(); | |||
|
32 | int valueAt(int row, int column); | |||
|
33 | ||||
|
34 | private: | |||
|
35 | int columnSum(int column); | |||
|
36 | ||||
|
37 | public Q_SLOTS: | |||
|
38 | ||||
|
39 | private: | |||
|
40 | ||||
|
41 | QAbstractItemModel* mModel; | |||
|
42 | StackedBarGroup* mStackedBarGroup; | |||
|
43 | }; | |||
|
44 | ||||
|
45 | QTCOMMERCIALCHART_END_NAMESPACE | |||
|
46 | ||||
|
47 | #endif // STACKEDBARCHARTSERIES_H |
@@ -0,0 +1,133 | |||||
|
1 | #include "stackedbargroup.h" | |||
|
2 | #include "bar.h" | |||
|
3 | #include <QDebug> | |||
|
4 | ||||
|
5 | QTCOMMERCIALCHART_BEGIN_NAMESPACE | |||
|
6 | ||||
|
7 | StackedBarGroup::StackedBarGroup(StackedBarChartSeries& series, QGraphicsItem *parent) : | |||
|
8 | ChartItem(parent) | |||
|
9 | ,mSeries(series) | |||
|
10 | ,mLayoutSet(false) | |||
|
11 | ,mLayoutDirty(true) | |||
|
12 | ,mBarDefaultWidth(10) // TODO: remove hard coding, when we have layout code ready | |||
|
13 | { | |||
|
14 | dataChanged(); | |||
|
15 | } | |||
|
16 | ||||
|
17 | ||||
|
18 | void StackedBarGroup::setSize(const QSize& size) | |||
|
19 | { | |||
|
20 | qDebug() << "StackedBarGroup::setSize"; | |||
|
21 | mWidth = size.width(); | |||
|
22 | mHeight = size.height(); | |||
|
23 | layoutChanged(); | |||
|
24 | mLayoutSet = true; | |||
|
25 | } | |||
|
26 | ||||
|
27 | void StackedBarGroup::setPlotDomain(const PlotDomain& data) | |||
|
28 | { | |||
|
29 | qDebug() << "StackedBarGroup::setPlotDomain"; | |||
|
30 | // TODO: | |||
|
31 | } | |||
|
32 | ||||
|
33 | void StackedBarGroup::setBarWidth( int w ) | |||
|
34 | { | |||
|
35 | mBarDefaultWidth = w; | |||
|
36 | } | |||
|
37 | ||||
|
38 | int StackedBarGroup::addColor( QColor color ) | |||
|
39 | { | |||
|
40 | int colorIndex = mColors.count(); | |||
|
41 | mColors.append(color); | |||
|
42 | return colorIndex; | |||
|
43 | } | |||
|
44 | ||||
|
45 | void StackedBarGroup::resetColors() | |||
|
46 | { | |||
|
47 | mColors.clear(); | |||
|
48 | } | |||
|
49 | ||||
|
50 | void StackedBarGroup::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) | |||
|
51 | { | |||
|
52 | if (!mLayoutSet) { | |||
|
53 | qDebug() << "QBarChart::paint called without layout set. Aborting."; | |||
|
54 | return; | |||
|
55 | } | |||
|
56 | if (mLayoutDirty) { | |||
|
57 | // Layout or data has changed. Need to redraw. | |||
|
58 | foreach(QGraphicsItem* i, childItems()) { | |||
|
59 | i->paint(painter,option,widget); | |||
|
60 | } | |||
|
61 | } | |||
|
62 | } | |||
|
63 | ||||
|
64 | QRectF StackedBarGroup::boundingRect() const | |||
|
65 | { | |||
|
66 | return QRectF(0,0,mWidth,mHeight); | |||
|
67 | } | |||
|
68 | ||||
|
69 | ||||
|
70 | void StackedBarGroup::dataChanged() | |||
|
71 | { | |||
|
72 | qDebug() << "QBarChart::dataChanged mSeries"; | |||
|
73 | ||||
|
74 | // Find out maximum and minimum of all series | |||
|
75 | mMax = mSeries.max(); | |||
|
76 | mMin = mSeries.min(); | |||
|
77 | ||||
|
78 | // Delete old bars | |||
|
79 | // Is this correct way to delete childItems? | |||
|
80 | foreach (QGraphicsItem* item, childItems()) { | |||
|
81 | delete item; | |||
|
82 | } | |||
|
83 | ||||
|
84 | // Create new graphic items for bars | |||
|
85 | int totalItems = mSeries.countTotalItems(); | |||
|
86 | for (int i=0; i<totalItems; i++) { | |||
|
87 | Bar *bar = new Bar(this); | |||
|
88 | childItems().append(bar); | |||
|
89 | } | |||
|
90 | ||||
|
91 | mLayoutDirty = true; | |||
|
92 | } | |||
|
93 | ||||
|
94 | void StackedBarGroup::layoutChanged() | |||
|
95 | { | |||
|
96 | // Scale bars to new layout | |||
|
97 | // Layout for bars: | |||
|
98 | if (mSeries.countRows() <= 0) { | |||
|
99 | // Nothing to do. | |||
|
100 | return; | |||
|
101 | } | |||
|
102 | ||||
|
103 | // TODO: better way to auto-layout | |||
|
104 | // Use reals for accurancy (implicit casting here, we get a warning) | |||
|
105 | qreal maxSum = mSeries.maxColumnSum(); | |||
|
106 | qreal h = mHeight; | |||
|
107 | qreal scale = (h / maxSum); | |||
|
108 | ||||
|
109 | int count = mSeries.countColumns(); | |||
|
110 | int posStepX = (mWidth / (count+1)); | |||
|
111 | ||||
|
112 | int itemIndex(0); | |||
|
113 | int xPos = (mWidth / (count+1)) - mSeries.countColumns() * mBarDefaultWidth /2; | |||
|
114 | for (int column = 0; column < mSeries.countColumns(); column++) { | |||
|
115 | int yPos = mHeight; | |||
|
116 | for (int row=0; row < mSeries.countRows(); row++) { | |||
|
117 | qDebug() << itemIndex; | |||
|
118 | int barHeight = mSeries.valueAt(row, column) * scale; | |||
|
119 | Bar* bar = reinterpret_cast<Bar*> (childItems().at(itemIndex)); | |||
|
120 | ||||
|
121 | // TODO: width settable per bar? | |||
|
122 | bar->resize(mBarDefaultWidth, barHeight); | |||
|
123 | bar->setColor(mColors.at(row)); | |||
|
124 | bar->setPos(xPos, yPos); | |||
|
125 | itemIndex++; | |||
|
126 | yPos += barHeight; | |||
|
127 | } | |||
|
128 | xPos += posStepX; | |||
|
129 | } | |||
|
130 | mLayoutDirty = true; | |||
|
131 | } | |||
|
132 | ||||
|
133 | QTCOMMERCIALCHART_END_NAMESPACE |
@@ -0,0 +1,55 | |||||
|
1 | #ifndef STACKEDBARGROUP_H | |||
|
2 | #define STACKEDBARGROUP_H | |||
|
3 | ||||
|
4 | #include "chartitem_p.h" | |||
|
5 | #include "bar.h" | |||
|
6 | #include "stackedbarchartseries.h" | |||
|
7 | ||||
|
8 | QTCOMMERCIALCHART_BEGIN_NAMESPACE | |||
|
9 | ||||
|
10 | class StackedBarGroup : public ChartItem | |||
|
11 | { | |||
|
12 | public: | |||
|
13 | StackedBarGroup(StackedBarChartSeries& series, QGraphicsItem *parent = 0); | |||
|
14 | ||||
|
15 | // From ChartItem | |||
|
16 | virtual void setSize(const QSize& size); | |||
|
17 | virtual void setPlotDomain(const PlotDomain& data); | |||
|
18 | ||||
|
19 | // Layout "api" | |||
|
20 | void setPos(qreal x, qreal y); | |||
|
21 | void setBarWidth( int w ); // Default width for each bar | |||
|
22 | ||||
|
23 | int addColor( QColor color ); | |||
|
24 | void resetColors(); | |||
|
25 | ||||
|
26 | // From QGraphicsItem | |||
|
27 | void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); | |||
|
28 | QRectF boundingRect() const; | |||
|
29 | ||||
|
30 | private: | |||
|
31 | ||||
|
32 | void dataChanged(); // data of series has changed -> need to recalculate bar sizes | |||
|
33 | void layoutChanged(); // layout has changed -> need to recalculate bar sizes | |||
|
34 | ||||
|
35 | private: | |||
|
36 | ||||
|
37 | // Data | |||
|
38 | StackedBarChartSeries& mSeries; | |||
|
39 | int mMin; // Min and max values of data. (updated when data is changed, used when drawing) | |||
|
40 | int mMax; | |||
|
41 | ||||
|
42 | int mHeight; // Layout spesific | |||
|
43 | int mWidth; | |||
|
44 | int mBarDefaultWidth; | |||
|
45 | ||||
|
46 | bool mLayoutSet; // True, if component has been laid out. | |||
|
47 | bool mLayoutDirty; | |||
|
48 | ||||
|
49 | QList<QColor> mColors; // List of colors for series for now | |||
|
50 | ||||
|
51 | }; | |||
|
52 | ||||
|
53 | QTCOMMERCIALCHART_END_NAMESPACE | |||
|
54 | ||||
|
55 | #endif // STACKEDBARGROUP_H |
General Comments 0
You need to be logged in to leave comments.
Login now