@@ -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