##// END OF EJS Templates
barchart separators fixed, layout fixed
sauimone -
r505:ffc461f7ce12
parent child
Show More
@@ -1,82 +1,81
1 1 #include <QApplication>
2 2 #include <QMainWindow>
3 3 #include <qchartview.h>
4 4 #include <qbarseries.h>
5 5 #include <qbarset.h>
6 6 #include <qchartaxis.h>
7 7 #include <QStringList>
8 8
9 9 QTCOMMERCIALCHART_USE_NAMESPACE
10 10
11 11 int main(int argc, char *argv[])
12 12 {
13 13 QApplication a(argc, argv);
14 14 QMainWindow window;
15 15
16 16 //! [1]
17 17 // Define categories
18 18 QStringList categories;
19 19 categories << "Jan" << "Feb" << "Mar" << "Apr" << "May" << "Jun";
20 20 //! [1]
21 21
22 22 //! [2]
23 23 // Create some test sets for chat
24 24
25 25 QBarSet *set0 = new QBarSet("Bub");
26 26 QBarSet *set1 = new QBarSet("Bob");
27 27 QBarSet *set2 = new QBarSet("Guybrush");
28 28 QBarSet *set3 = new QBarSet("Larry");
29 29 QBarSet *set4 = new QBarSet("Zak");
30 30
31 31 *set0 << 1 << 2 << 3 << 4 << 5 << 6;
32 32 *set1 << 5 << 0 << 0 << 4 << 0 << 7;
33 33 *set2 << 3 << 5 << 8 << 13 << 8 << 5;
34 34 *set3 << 5 << 6 << 7 << 3 << 4 << 5;
35 35 *set4 << 9 << 7 << 5 << 3 << 1 << 2;
36 36 //! [2]
37 37
38 38 //! [3]
39 39 // Create series and add sets to it
40 40 QBarSeries* series= new QBarSeries(categories);
41 41
42 42 series->addBarSet(set0);
43 43 series->addBarSet(set1);
44 44 series->addBarSet(set2);
45 45 series->addBarSet(set3);
46 46 series->addBarSet(set4);
47 47 //! [3]
48 48
49 49 //! [4]
50 50 // Enable tooltip
51 51 series->setToolTipEnabled();
52 series->setSeparatorsVisible(true);
52 53
53 54 // Connect clicked signal of set to toggle floating values of set.
54 // Note that we leave QBarset "Zak" unconnected here, so clicking on it doesn't toggle values.
55 55 QObject::connect(set0,SIGNAL(clicked(QString)),set0,SIGNAL(toggleFloatingValues()));
56 56 QObject::connect(set1,SIGNAL(clicked(QString)),set1,SIGNAL(toggleFloatingValues()));
57 57 QObject::connect(set2,SIGNAL(clicked(QString)),set2,SIGNAL(toggleFloatingValues()));
58 58 QObject::connect(set3,SIGNAL(clicked(QString)),set3,SIGNAL(toggleFloatingValues()));
59 QObject::connect(set4,SIGNAL(clicked(QString)),set4,SIGNAL(toggleFloatingValues()));
59 60 //! [4]
60 61
61 62 //! [5]
62 63 // Create view for chart and add series to it. Apply theme.
63 64
64 65 QChartView* chartView = new QChartView(&window);
65 66 chartView->addSeries(series);
66 67 chartView->setChartTitle("simple barchart");
67 68 chartView->setChartTheme(QChart::ChartThemeIcy);
68 69 //! [5]
69 70
70 71 //! [6]
71 chartView->axisX()->setAxisVisible(false);
72 72 chartView->axisX()->setGridVisible(false);
73 chartView->axisX()->setLabelsVisible(false);
74 73 //! [6]
75 74
76 75 window.setCentralWidget(chartView);
77 76 window.resize(400, 300);
78 77 window.show();
79 78
80 79 return a.exec();
81 80 }
82 81
@@ -1,81 +1,79
1 1 #include <QApplication>
2 2 #include <QMainWindow>
3 3 #include <qchartview.h>
4 4 #include <qstackedbarseries.h>
5 5 #include <qbarset.h>
6 6 #include <qchartaxis.h>
7 7 #include <QStringList>
8 8
9 9 QTCOMMERCIALCHART_USE_NAMESPACE
10 10
11 11 int main(int argc, char *argv[])
12 12 {
13 13 QApplication a(argc, argv);
14 14 QMainWindow window;
15 15
16 16 //! [1]
17 17 // Define categories
18 18 QStringList categories;
19 19 categories << "Jan" << "Feb" << "Mar" << "Apr" << "May" << "Jun";
20 20 //! [1]
21 21
22 22 //! [2]
23 23 // Create some test sets for chat
24 24 QBarSet *set0 = new QBarSet("Bub");
25 25 QBarSet *set1 = new QBarSet("Bob");
26 26 QBarSet *set2 = new QBarSet("Guybrush");
27 27 QBarSet *set3 = new QBarSet("Larry");
28 28 QBarSet *set4 = new QBarSet("Zak");
29 29
30 30 *set0 << 1 << 2 << 3 << 4 << 5 << 6;
31 31 *set1 << 5 << 0 << 0 << 4 << 0 << 7;
32 32 *set2 << 3 << 5 << 8 << 13 << 8 << 5;
33 33 *set3 << 5 << 6 << 7 << 3 << 4 << 5;
34 34 *set4 << 9 << 7 << 5 << 3 << 1 << 2;
35 35 //! [2]
36 36
37 37 //! [3]
38 38 // Create series and add sets to it
39 39 QStackedBarSeries* series = new QStackedBarSeries(categories);
40 40
41 41 series->addBarSet(set0);
42 42 series->addBarSet(set1);
43 43 series->addBarSet(set2);
44 44 series->addBarSet(set3);
45 45 series->addBarSet(set4);
46 46 //! [3]
47 47
48 48 //! [4]
49 49 // Enable tooltip
50 50 series->setToolTipEnabled();
51 51
52 52 // Connect clicked signal of set to toggle floating values of set.
53 // Note that we leave QBarset "Zak" unconnected here, so clicking on it doesn't toggle values.
54 53 QObject::connect(set0,SIGNAL(clicked(QString)),set0,SIGNAL(toggleFloatingValues()));
55 54 QObject::connect(set1,SIGNAL(clicked(QString)),set1,SIGNAL(toggleFloatingValues()));
56 55 QObject::connect(set2,SIGNAL(clicked(QString)),set2,SIGNAL(toggleFloatingValues()));
57 56 QObject::connect(set3,SIGNAL(clicked(QString)),set3,SIGNAL(toggleFloatingValues()));
57 QObject::connect(set4,SIGNAL(clicked(QString)),set4,SIGNAL(toggleFloatingValues()));
58 58 //! [4]
59 59
60 60 //! [5]
61 61 // Create view for chart and add series to it. Apply theme.
62 62
63 63 QChartView* chartView = new QChartView(&window);
64 64 chartView->addSeries(series);
65 65 chartView->setChartTitle("simple stacked barchart");
66 66 chartView->setChartTheme(QChart::ChartThemeIcy);
67 67 //! [5]
68 68
69 69 //! [6]
70 chartView->axisX()->setAxisVisible(false);
71 70 chartView->axisX()->setGridVisible(false);
72 chartView->axisX()->setLabelsVisible(false);
73 71 //! [6]
74 72
75 73 window.setCentralWidget(chartView);
76 74 window.resize(400, 300);
77 75 window.show();
78 76
79 77 return a.exec();
80 78 }
81 79
@@ -1,85 +1,95
1 1 #include "barpresenter_p.h"
2 2 #include "bar_p.h"
3 3 #include "barvalue_p.h"
4 #include "separator_p.h"
4 5 #include "qbarset.h"
5 6 #include <QDebug>
6 7
7 8 QTCOMMERCIALCHART_BEGIN_NAMESPACE
8 9
9 10 BarPresenter::BarPresenter(QBarSeries *series, QChart *parent) :
10 11 BarPresenterBase(series, parent)
11 12 {
12 13 }
13 14
14 15 void BarPresenter::layoutChanged()
15 16 {
16 17 // Scale bars to new layout
17 18 // Layout for bars:
18 19 if (mSeries->barsetCount() <= 0) {
19 20 qDebug() << "No sets in model!";
20 21 return;
21 22 }
22 23
23 24 if (childItems().count() == 0) {
24 25 qDebug() << "WARNING: BarPresenter::layoutChanged called before graphics items are created!";
25 26 return;
26 27 }
27 28
28 29 // Use temporary qreals for accurancy (we might get some compiler warnings... :)
29 30 int categoryCount = mSeries->categoryCount();
30 31 int setCount = mSeries->barsetCount();
31 32
32 33 qreal tW = mWidth;
33 34 qreal tH = mHeight;
34 35 qreal tM = mSeries->max();
35 36 qreal scale = (tH/tM);
36 37 qreal tC = categoryCount + 1;
37 mBarWidth = tW / ((categoryCount * setCount) + tC);
38 qreal xStepPerCategory = (tW/tC) + mBarWidth;
38 qreal categoryWidth = tW/tC;
39 mBarWidth = categoryWidth / (setCount+1);
39 40
40 41 int itemIndex(0);
41 42 for (int category=0; category < categoryCount; category++) {
42 qreal xPos = xStepPerCategory * category;
43 qreal xPos = categoryWidth * category + categoryWidth /2;
43 44 qreal yPos = mHeight;
44 45 for (int set = 0; set < setCount; set++) {
45 46 qreal barHeight = mSeries->valueAt(set,category) * scale;
46 47 Bar* bar = mBars.at(itemIndex);
47 48
48 49 // TODO: width settable per bar?
49 50 bar->resize(mBarWidth, barHeight);
50 51 bar->setBrush(mSeries->barsetAt(set)->brush());
51 52 bar->setPos(xPos, yPos-barHeight);
52 53 itemIndex++;
53 54 xPos += mBarWidth;
54 55 }
55 56 }
56 57
58 // Position separators
59 qreal xPos = categoryWidth + categoryWidth/2 - mBarWidth /2;
60 for (int s=0; s < mSeparators.count(); s++) {
61 Separator* sep = mSeparators.at(s);
62 sep->setPos(xPos,0);
63 sep->setSize(QSizeF(1,mHeight));
64 xPos += categoryWidth;
65 }
66
57 67 // Position floating values
58 68 itemIndex = 0;
59 69 for (int category=0; category < mSeries->categoryCount(); category++) {
60 qreal xPos = xStepPerCategory * category + mBarWidth/2;
70 qreal xPos = categoryWidth * category + categoryWidth/2 + mBarWidth/2;
61 71 qreal yPos = mHeight;
62 72 for (int set=0; set < mSeries->barsetCount(); set++) {
63 73 qreal barHeight = mSeries->valueAt(set,category) * scale;
64 74 BarValue* value = mFloatingValues.at(itemIndex);
65 75
66 76 // TODO: remove hard coding, apply layout
67 77 value->resize(100,50);
68 78 value->setPos(xPos, yPos-barHeight/2);
69 79 value->setPen(QPen(QColor(255,255,255,255)));
70 80
71 81 if (mSeries->valueAt(set,category) != 0) {
72 82 value->setValueString(QString::number(mSeries->valueAt(set,category)));
73 83 } else {
74 84 value->setValueString(QString(""));
75 85 }
76 86
77 87 itemIndex++;
78 88 xPos += mBarWidth;
79 89 }
80 90 }
81 91 }
82 92
83 93 #include "moc_barpresenter_p.cpp"
84 94
85 95 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,178 +1,179
1 1 #include "barpresenterbase_p.h"
2 2 #include "bar_p.h"
3 3 #include "barvalue_p.h"
4 4 #include "separator_p.h"
5 5 #include "qbarset.h"
6 6 #include "qbarseries.h"
7 7 #include "qchart.h"
8 8 #include "qchartaxis.h"
9 9 #include "qchartaxiscategories.h"
10 10 #include <QDebug>
11 11 #include <QToolTip>
12 12
13 13 QTCOMMERCIALCHART_BEGIN_NAMESPACE
14 14
15 15 BarPresenterBase::BarPresenterBase(QBarSeries *series, QChart *parent)
16 16 : ChartItem(parent)
17 17 ,mLayoutSet(false)
18 ,mSeparatorsEnabled(false)
19 18 ,mSeries(series)
20 19 ,mChart(parent)
21 20 {
22 21 connect(series,SIGNAL(showToolTip(QPoint,QString)),this,SLOT(showToolTip(QPoint,QString)));
22 connect(series,SIGNAL(enableSeparators(bool)),this,SLOT(enableSeparators(bool)));
23 enableSeparators(series->separatorsVisible());
23 24 initAxisLabels();
24 25 dataChanged();
25 26 }
26 27
27 28 BarPresenterBase::~BarPresenterBase()
28 29 {
29 30 disconnect(this,SLOT(showToolTip(QPoint,QString)));
31 disconnect(this,SLOT(enableSeparators(bool)));
30 32 }
31 33
32 34 void BarPresenterBase::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
33 35 {
34 36 if (!mLayoutSet) {
35 37 qDebug() << "BarPresenterBase::paint called without layout set. Aborting.";
36 38 return;
37 39 }
38 40 foreach(QGraphicsItem* i, childItems()) {
39 41 i->paint(painter,option,widget);
40 42 }
41 43 }
42 44
43 45 QRectF BarPresenterBase::boundingRect() const
44 46 {
45 47 return QRectF(0,0,mWidth,mHeight);
46 48 }
47 49
48 50 void BarPresenterBase::dataChanged()
49 51 {
50 52 // TODO: performance optimizations. Do we really need to delete and create items every time data is changed or can we reuse them?
51 53 // Delete old bars
52 54 foreach (QGraphicsItem* item, childItems()) {
53 55 delete item;
54 56 }
55 57
56 58 mBars.clear();
57 59 mSeparators.clear();
58 60 mFloatingValues.clear();
59 61
60 62 // Create new graphic items for bars
61 63 for (int c=0; c<mSeries->categoryCount(); c++) {
62 64 QString category = mSeries->categoryName(c);
63 65 for (int s=0; s<mSeries->barsetCount(); s++) {
64 66 QBarSet *set = mSeries->barsetAt(s);
65 67 Bar *bar = new Bar(category,this);
66 68 childItems().append(bar);
67 69 mBars.append(bar);
68 70 connect(bar,SIGNAL(clicked(QString)),set,SIGNAL(clicked(QString)));
69 71 connect(bar,SIGNAL(rightClicked(QString)),set,SIGNAL(rightClicked(QString)));
70 72 connect(bar,SIGNAL(hoverEntered(QPoint)),set,SLOT(barHoverEnterEvent(QPoint)));
71 73 connect(bar,SIGNAL(hoverLeaved()),set,SLOT(barHoverLeaveEvent()));
72 74 }
73 75 }
74 76
75 77 // Create separators
76 78 int count = mSeries->categoryCount() - 1; // There is one less separator than columns
77 79 for (int i=0; i<count; i++) {
78 80 Separator* sep = new Separator(this);
79 81 sep->setColor(QColor(255,0,0,255)); // TODO: color for separations from theme
80 sep->setVisible(mSeparatorsEnabled);
82 sep->setVisible(mSeries->separatorsVisible());
81 83 childItems().append(sep);
82 84 mSeparators.append(sep);
83 85 }
84 86
85 87 // Create floating values
86 88 for (int category=0; category<mSeries->categoryCount(); category++) {
87 89 for (int s=0; s<mSeries->barsetCount(); s++) {
88 90 QBarSet *set = mSeries->barsetAt(s);
89 91 BarValue *value = new BarValue(*set, this);
90 92 childItems().append(value);
91 93 mFloatingValues.append(value);
92 94 connect(set,SIGNAL(toggleFloatingValues()),value,SLOT(toggleVisible()));
93 95 }
94 96 }
95 97 }
96 98
97 99 void BarPresenterBase::initAxisLabels()
98 100 {
99 101 int count = mSeries->categoryCount();
100 102 if (0 == count) {
101 103 return;
102 104 }
103 105
104 106 mChart->axisX()->setTicksCount(count+2);
105 107
106 108 qreal min = 0;
107 109 qreal max = count+1;
108 110
109 111 mChart->axisX()->setMin(min);
110 112 mChart->axisX()->setMax(max);
111 113
112 114 QChartAxisCategories* categories = mChart->axisX()->categories();
113 115 categories->clear();
114 116 for (int i=0; i<count; i++) {
115 117 categories->insert(i+1,mSeries->categoryName(i));
116 118 }
117 119
118 120
119 121
120 122 mChart->axisX()->setLabelsVisible(true);
121 123 }
122 124
123 125 //handlers
124 126
125 127 void BarPresenterBase::handleModelChanged(int index)
126 128 {
127 129 // qDebug() << "BarPresenterBase::handleModelChanged" << index;
128 130 dataChanged();
129 131 }
130 132
131 133 void BarPresenterBase::handleDomainChanged(const Domain& domain)
132 134 {
133 135 qDebug() << "BarPresenterBase::handleDomainChanged";
134 136 /*
135 137 int count = mSeries->categoryCount();
136 138 if (0 == count) {
137 139 return;
138 140 }
139 141
140 142 // Position labels to domain
141 143 qreal min = domain.minX();
142 144 qreal max = domain.maxX();
143 145 qreal step = (max-min)/count;
144 146 QChartAxisCategories& categories = mChart->axisX()->categories();
145 147 categories.clear();
146 148 for (int i=0; i<count; i++) {
147 149 categories.insert(min,mSeries->categoryName(i));
148 150 min += step;
149 151 }
150 152 */
151 153 }
152 154
153 155 void BarPresenterBase::handleGeometryChanged(const QRectF& rect)
154 156 {
155 157 mWidth = rect.width();
156 158 mHeight = rect.height();
157 159 layoutChanged();
158 160 mLayoutSet = true;
159 161 setPos(rect.topLeft());
160 162 }
161 163
162 164 void BarPresenterBase::showToolTip(QPoint pos, QString tip)
163 165 {
164 166 // TODO: cool tooltip instead of default
165 167 QToolTip::showText(pos,tip);
166 168 }
167 169
168 170 void BarPresenterBase::enableSeparators(bool enabled)
169 171 {
170 172 for (int i=0; i<mSeparators.count(); i++) {
171 173 mSeparators.at(i)->setVisible(enabled);
172 174 }
173 mSeparatorsEnabled = enabled;
174 175 }
175 176
176 177 #include "moc_barpresenterbase_p.cpp"
177 178
178 179 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,68 +1,67
1 1 #ifndef BARPRESENTERBASE_H
2 2 #define BARPRESENTERBASE_H
3 3
4 4 #include "chartitem_p.h"
5 5 #include "qbarseries.h"
6 6 #include <QPen>
7 7 #include <QBrush>
8 8 #include <QGraphicsItem>
9 9
10 10 QTCOMMERCIALCHART_BEGIN_NAMESPACE
11 11
12 12 class Bar;
13 13 class Separator;
14 14 class BarValue;
15 15 class QChartAxisCategories;
16 16 class QChart;
17 17
18 18 // Common implemantation of different presenters. Not to be instantiated.
19 19 // TODO: combine this with BarPresenter and derive other presenters from it?
20 20 class BarPresenterBase : public QObject, public ChartItem
21 21 {
22 22 Q_OBJECT
23 23 public:
24 24 BarPresenterBase(QBarSeries *series, QChart *parent = 0);
25 25 virtual ~BarPresenterBase();
26 26
27 27 public:
28 28 // From QGraphicsItem
29 29 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
30 30 QRectF boundingRect() const;
31 31
32 32 // TODO: Consider the domain for layoutChanged. May be use case, may not be. If it is, then the derived classes need to implement it
33 33 virtual void dataChanged(); // data of series has changed -> need to recalculate bar sizes
34 34 virtual void layoutChanged() = 0; // layout has changed -> need to recalculate bar sizes
35 35
36 36 protected:
37 37 void initAxisLabels();
38 38
39 39 public slots:
40 40 void handleModelChanged(int index);
41 41 void handleDomainChanged(const Domain& domain);
42 42 void handleGeometryChanged(const QRectF& size);
43 43
44 44 // Internal slots
45 45 void showToolTip(QPoint pos, QString tip); // shows tooltip (if enabled)
46 46 void enableSeparators(bool enabled);
47 47
48 48 protected:
49 49
50 50 // TODO: consider these.
51 51 int mHeight; // Layout spesific
52 52 int mWidth;
53 53 qreal mBarWidth;
54 54
55 55 bool mLayoutSet; // True, if component has been laid out.
56 bool mSeparatorsEnabled;
57 56
58 57 // Not owned.
59 58 QBarSeries* mSeries;
60 59 QList<Bar*> mBars;
61 60 QList<Separator*> mSeparators;
62 61 QList<BarValue*> mFloatingValues;
63 62 QChart* mChart;
64 63 };
65 64
66 65 QTCOMMERCIALCHART_END_NAMESPACE
67 66
68 67 #endif // BARPRESENTERBASE_H
@@ -1,222 +1,227
1 1 #include <QDebug>
2 2 #include "qbarseries.h"
3 3 #include "qbarset.h"
4 4 #include "barchartmodel_p.h"
5 5
6 6 QTCOMMERCIALCHART_BEGIN_NAMESPACE
7 7
8 8 /*!
9 9 \class QBarSeries
10 10 \brief part of QtCommercial chart API.
11 11
12 12 QBarSeries represents a series of data shown as bars. One QBarSeries can contain multible
13 13 QBarSet data sets. QBarSeries groups the data from sets to categories, which are defined
14 14 by QStringList.
15 15
16 16 \mainclass
17 17
18 18 \sa QBarSet, QStackedBarSeries, QPercentBarSeries
19 19 */
20 20
21 21 /*!
22 22 \fn virtual QSeriesType QBarSeries::type() const
23 23 \brief Returns type of series.
24 24 \sa QSeries, QSeriesType
25 25 */
26 26
27 27 /*!
28 28 \fn void QBarSeries::showToolTip(QPoint pos, QString tip)
29 29 \brief \internal \a pos \a tip
30 30 */
31 31
32 32 /*!
33 33 Constructs empty QBarSeries. Parameter \a categories defines the categories for chart.
34 34 QBarSeries is QObject which is a child of a \a parent.
35 35 */
36 36 QBarSeries::QBarSeries(QStringList categories, QObject *parent)
37 37 : QSeries(parent)
38 38 ,mModel(new BarChartModel(categories, this))
39 39 {
40 40 }
41 41
42 42 /*!
43 43 Adds a set of bars to series. Takes ownership of \a set.
44 44 Connects the clicked(QString) and rightClicked(QString) signals
45 45 of \a set to this series
46 46 */
47 47 void QBarSeries::addBarSet(QBarSet *set)
48 48 {
49 49 mModel->addBarSet(set);
50 50 connect(set,SIGNAL(clicked(QString)),this,SLOT(barsetClicked(QString)));
51 51 connect(set,SIGNAL(rightClicked(QString)),this,SLOT(barsetRightClicked(QString)));
52 52 }
53 53
54 54 /*!
55 55 Removes a set of bars from series. Releases ownership of \a set. Doesnt delete \a set.
56 56 Disconnects the clicked(QString) and rightClicked(QString) signals
57 57 of \a set from this series
58 58 */
59 59 void QBarSeries::removeBarSet(QBarSet *set)
60 60 {
61 61 disconnect(set,SIGNAL(clicked(QString)),this,SLOT(barsetClicked(QString)));
62 62 disconnect(set,SIGNAL(rightClicked(QString)),this,SLOT(barsetRightClicked(QString)));
63 63 mModel->removeBarSet(set);
64 64 }
65 65
66 66 /*!
67 67 Returns number of sets in series.
68 68 */
69 69 int QBarSeries::barsetCount()
70 70 {
71 71 return mModel->barsetCount();
72 72 }
73 73
74 74 /*!
75 75 Returns number of categories in series
76 76 */
77 77 int QBarSeries::categoryCount()
78 78 {
79 79 return mModel->categoryCount();
80 80 }
81 81
82 82 /*!
83 83 Returns a list of sets in series. Keeps ownership of sets.
84 84 */
85 85 QList<QBarSet*> QBarSeries::barSets()
86 86 {
87 87 return mModel->barSets();
88 88 }
89 89
90 90 /*!
91 91 \internal \a index
92 92 */
93 93 QBarSet* QBarSeries::barsetAt(int index)
94 94 {
95 95 return mModel->setAt(index);
96 96 }
97 97
98 98 /*!
99 99 Returns legend of series.
100 100 */
101 101 QList<QSeries::Legend> QBarSeries::legend()
102 102 {
103 103 return mModel->legend();
104 104 }
105 105
106 106 /*!
107 107 \internal \a category
108 108 */
109 109 QString QBarSeries::categoryName(int category)
110 110 {
111 111 return mModel->categoryName(category);
112 112 }
113 113
114 114 /*!
115 115 Enables or disables tooltip depending on parameter \a enabled.
116 116 Tooltip shows the name of set, when mouse is hovering on top of bar.
117 117 Calling without parameter \a enabled, enables the tooltip
118 118 */
119 119 void QBarSeries::setToolTipEnabled(bool enabled)
120 120 {
121 121 // TODO: what if we add sets after call to this function? Those sets won't have tooltip enabled.
122 122 if (enabled) {
123 123 for (int i=0; i<mModel->barsetCount(); i++) {
124 124 QBarSet *set = mModel->setAt(i);
125 125 connect(set,SIGNAL(showToolTip(QPoint,QString)),this,SIGNAL(showToolTip(QPoint,QString)));
126 126 }
127 127 } else {
128 128 for (int i=0; i<mModel->barsetCount(); i++) {
129 129 QBarSet *set = mModel->setAt(i);
130 130 disconnect(set,SIGNAL(showToolTip(QPoint,QString)),this,SIGNAL(showToolTip(QPoint,QString)));
131 131 }
132 132 }
133 133 }
134 134
135 135 /*!
136 136 Enables or disables separators depending on parameter \a enabled.
137 137 Separators are visual elements that are drawn between categories.
138 138 Calling without parameter \a enabled, enables the separators
139 139 */
140 void QBarSeries::setSeparatorsEnabled(bool enabled)
140 void QBarSeries::setSeparatorsVisible(bool visible)
141 141 {
142 // TODO: toggle
143 // emit separatorsEnabled(enabled);
142 mSeparatorsVisible = visible;
143 emit enableSeparators(visible);
144 144 }
145 145
146 146
147 147 /*!
148 148 \internal \a category
149 149 */
150 150 void QBarSeries::barsetClicked(QString category)
151 151 {
152 152 emit clicked(qobject_cast<QBarSet*>(sender()), category);
153 153 }
154 154
155 155 /*!
156 156 \internal \a category
157 157 */
158 158 void QBarSeries::barsetRightClicked(QString category)
159 159 {
160 160 emit rightClicked(qobject_cast<QBarSet*>(sender()), category);
161 161 }
162 162
163 163
164 164 /*!
165 165 \internal
166 166 */
167 167 qreal QBarSeries::min()
168 168 {
169 169 return mModel->min();
170 170 }
171 171
172 172 /*!
173 173 \internal
174 174 */
175 175 qreal QBarSeries::max()
176 176 {
177 177 return mModel->max();
178 178 }
179 179
180 180 /*!
181 181 \internal \a set \a category
182 182 */
183 183 qreal QBarSeries::valueAt(int set, int category)
184 184 {
185 185 return mModel->valueAt(set,category);
186 186 }
187 187
188 188 /*!
189 189 \internal \a set \a category
190 190 */
191 191 qreal QBarSeries::percentageAt(int set, int category)
192 192 {
193 193 return mModel->percentageAt(set,category);
194 194 }
195 195
196 196 /*!
197 197 \internal \a category
198 198 */
199 199 qreal QBarSeries::categorySum(int category)
200 200 {
201 201 return mModel->categorySum(category);
202 202 }
203 203
204 204 /*!
205 205 \internal
206 206 */
207 207 qreal QBarSeries::maxCategorySum()
208 208 {
209 209 return mModel->maxCategorySum();
210 210 }
211 211
212 212 /*!
213 213 \internal
214 214 */
215 215 BarChartModel& QBarSeries::model()
216 216 {
217 217 return *mModel;
218 218 }
219 219
220 bool QBarSeries::separatorsVisible()
221 {
222 return mSeparatorsVisible;
223 }
224
220 225 #include "moc_qbarseries.cpp"
221 226
222 227 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,69 +1,72
1 1 #ifndef BARSERIES_H
2 2 #define BARSERIES_H
3 3
4 4 #include "qseries.h"
5 5 #include <QStringList>
6 6
7 7 QTCOMMERCIALCHART_BEGIN_NAMESPACE
8 8
9 9 class QBarSet;
10 10 class BarChartModel;
11 11 class BarCategory;
12 12
13 13 // Container for series
14 14 class QTCOMMERCIALCHART_EXPORT QBarSeries : public QSeries
15 15 {
16 16 Q_OBJECT
17 17 public:
18 18 QBarSeries(QStringList categories, QObject* parent=0);
19 19
20 20 virtual QSeriesType type() const { return QSeries::SeriesTypeBar; }
21 21
22 22 void addBarSet(QBarSet *set); // Takes ownership of set
23 23 void removeBarSet(QBarSet *set); // Releases ownership, doesn't delete set
24 24 int barsetCount();
25 25 int categoryCount();
26 26 QList<QBarSet*> barSets();
27 27 QList<QSeries::Legend> legend();
28 28
29 29 public:
30 30 // TODO: Functions below this are not part of api and will be moved
31 31 // to private implementation, when we start using it
32 32 // TODO: TO PIMPL --->
33 33 QBarSet* barsetAt(int index);
34 34 QString categoryName(int category);
35 35 qreal min();
36 36 qreal max();
37 37 qreal valueAt(int set, int category);
38 38 qreal percentageAt(int set, int category);
39 39 qreal categorySum(int category);
40 40 qreal maxCategorySum();
41 41 BarChartModel& model();
42 bool separatorsVisible();
42 43 // <--- TO PIMPL
43 44
44 45 signals:
45 46 //void changed(int index);
46 47 void clicked(QBarSet* barset, QString category); // Up to user of api, what to do with these signals
47 48 void rightClicked(QBarSet* barset, QString category);
48 49
49 50 // TODO: internal signals, these to private implementation.
50 51 // TODO: TO PIMPL --->
52 void enableSeparators(bool enable);
51 53 void showToolTip(QPoint pos, QString tip);
52 54 // <--- TO PIMPL
53 55
54 56 public Q_SLOTS:
55 57 void setToolTipEnabled(bool enabled=true); // enables tooltips
56 void setSeparatorsEnabled(bool enabled=true); // enables separators between categories
58 void setSeparatorsVisible(bool visible=true); // enables separators between categories
57 59
58 60 // TODO: TO PIMPL --->
59 61 void barsetClicked(QString category);
60 62 void barsetRightClicked(QString category);
61 63 // <--- TO PIMPL
62 64
63 65 protected:
64 66 BarChartModel* mModel;
67 bool mSeparatorsVisible;
65 68 };
66 69
67 70 QTCOMMERCIALCHART_END_NAMESPACE
68 71
69 72 #endif // BARSERIES_H
@@ -1,369 +1,369
1 1 #include "mainwidget.h"
2 2 #include "dataseriedialog.h"
3 3 #include <qpieseries.h>
4 4 #include <qscatterseries.h>
5 5 #include <qlineseries.h>
6 6 #include <qareaseries.h>
7 7 #include <qsplineseries.h>
8 8 #include <qbarset.h>
9 9 #include <qbarseries.h>
10 10 #include <qstackedbarseries.h>
11 11 #include <qpercentbarseries.h>
12 12 #include <QPushButton>
13 13 #include <QComboBox>
14 14 #include <QSpinBox>
15 15 #include <QCheckBox>
16 16 #include <QGridLayout>
17 17 #include <QHBoxLayout>
18 18 #include <QLabel>
19 19 #include <QSpacerItem>
20 20 #include <QMessageBox>
21 21 #include <cmath>
22 22 #include <QDebug>
23 23 #include <QStandardItemModel>
24 24
25 25
26 26 QTCOMMERCIALCHART_USE_NAMESPACE
27 27
28 28 MainWidget::MainWidget(QWidget *parent) :
29 29 QWidget(parent),
30 30 m_addSerieDialog(0),
31 31 m_chartView(0)
32 32 {
33 33 m_chartView = new QChartView(this);
34 34 m_chartView->setRubberBandPolicy(QChartView::HorizonalRubberBand);
35 35
36 36 // Grid layout for the controls for configuring the chart widget
37 37 QGridLayout *grid = new QGridLayout();
38 38 QPushButton *addSeriesButton = new QPushButton("Add series");
39 39 connect(addSeriesButton, SIGNAL(clicked()), this, SLOT(addSeries()));
40 40 grid->addWidget(addSeriesButton, 0, 1);
41 41 initBackroundCombo(grid);
42 42 initScaleControls(grid);
43 43 initThemeCombo(grid);
44 44 initCheckboxes(grid);
45 45
46 46 // add row with empty label to make all the other rows static
47 47 grid->addWidget(new QLabel(""), grid->rowCount(), 0);
48 48 grid->setRowStretch(grid->rowCount() - 1, 1);
49 49
50 50 // Another grid layout as a main layout
51 51 QGridLayout *mainLayout = new QGridLayout();
52 52 mainLayout->addLayout(grid, 0, 0);
53 53
54 54 // Add layouts and the chart widget to the main layout
55 55 mainLayout->addWidget(m_chartView, 0, 1, 3, 1);
56 56 setLayout(mainLayout);
57 57 }
58 58
59 59 // Combo box for selecting the chart's background
60 60 void MainWidget::initBackroundCombo(QGridLayout *grid)
61 61 {
62 62 QComboBox *backgroundCombo = new QComboBox(this);
63 63 backgroundCombo->addItem("Color");
64 64 backgroundCombo->addItem("Gradient");
65 65 backgroundCombo->addItem("Image");
66 66 connect(backgroundCombo, SIGNAL(currentIndexChanged(int)),
67 67 this, SLOT(backgroundChanged(int)));
68 68
69 69 grid->addWidget(new QLabel("Background:"), grid->rowCount(), 0);
70 70 grid->addWidget(backgroundCombo, grid->rowCount() - 1, 1);
71 71 }
72 72
73 73 // Scale related controls (auto-scale vs. manual min-max values)
74 74 void MainWidget::initScaleControls(QGridLayout *grid)
75 75 {
76 76 m_autoScaleCheck = new QCheckBox("Automatic scaling");
77 77 connect(m_autoScaleCheck, SIGNAL(stateChanged(int)), this, SLOT(autoScaleChanged(int)));
78 78 // Allow setting also non-sense values (like -2147483648 and 2147483647)
79 79 m_xMinSpin = new QSpinBox();
80 80 m_xMinSpin->setMinimum(INT_MIN);
81 81 m_xMinSpin->setMaximum(INT_MAX);
82 82 m_xMinSpin->setValue(0);
83 83 connect(m_xMinSpin, SIGNAL(valueChanged(int)), this, SLOT(xMinChanged(int)));
84 84 m_xMaxSpin = new QSpinBox();
85 85 m_xMaxSpin->setMinimum(INT_MIN);
86 86 m_xMaxSpin->setMaximum(INT_MAX);
87 87 m_xMaxSpin->setValue(10);
88 88 connect(m_xMaxSpin, SIGNAL(valueChanged(int)), this, SLOT(xMaxChanged(int)));
89 89 m_yMinSpin = new QSpinBox();
90 90 m_yMinSpin->setMinimum(INT_MIN);
91 91 m_yMinSpin->setMaximum(INT_MAX);
92 92 m_yMinSpin->setValue(0);
93 93 connect(m_yMinSpin, SIGNAL(valueChanged(int)), this, SLOT(yMinChanged(int)));
94 94 m_yMaxSpin = new QSpinBox();
95 95 m_yMaxSpin->setMinimum(INT_MIN);
96 96 m_yMaxSpin->setMaximum(INT_MAX);
97 97 m_yMaxSpin->setValue(10);
98 98 connect(m_yMaxSpin, SIGNAL(valueChanged(int)), this, SLOT(yMaxChanged(int)));
99 99
100 100 grid->addWidget(m_autoScaleCheck, grid->rowCount(), 0);
101 101 grid->addWidget(new QLabel("x min:"), grid->rowCount(), 0);
102 102 grid->addWidget(m_xMinSpin, grid->rowCount() - 1, 1);
103 103 grid->addWidget(new QLabel("x max:"), grid->rowCount(), 0);
104 104 grid->addWidget(m_xMaxSpin, grid->rowCount() - 1, 1);
105 105 grid->addWidget(new QLabel("y min:"), grid->rowCount(), 0);
106 106 grid->addWidget(m_yMinSpin, grid->rowCount() - 1, 1);
107 107 grid->addWidget(new QLabel("y max:"), grid->rowCount(), 0);
108 108 grid->addWidget(m_yMaxSpin, grid->rowCount() - 1, 1);
109 109
110 110 m_autoScaleCheck->setChecked(true);
111 111 }
112 112
113 113 // Combo box for selecting theme
114 114 void MainWidget::initThemeCombo(QGridLayout *grid)
115 115 {
116 116 QComboBox *chartTheme = new QComboBox();
117 117 chartTheme->addItem("Default");
118 118 chartTheme->addItem("Vanilla");
119 119 chartTheme->addItem("Icy");
120 120 chartTheme->addItem("Grayscale");
121 121 chartTheme->addItem("Scientific");
122 122 chartTheme->addItem("Unnamed1");
123 123 connect(chartTheme, SIGNAL(currentIndexChanged(int)),
124 124 this, SLOT(changeChartTheme(int)));
125 125 grid->addWidget(new QLabel("Chart theme:"), 8, 0);
126 126 grid->addWidget(chartTheme, 8, 1);
127 127 }
128 128
129 129 // Different check boxes for customizing chart
130 130 void MainWidget::initCheckboxes(QGridLayout *grid)
131 131 {
132 132 // TODO: setZoomEnabled slot has been removed from QChartView -> Re-implement zoom on/off
133 133 QCheckBox *zoomCheckBox = new QCheckBox("Drag'n drop Zoom");
134 134 connect(zoomCheckBox, SIGNAL(toggled(bool)), m_chartView, SLOT(setZoomEnabled(bool)));
135 135 zoomCheckBox->setChecked(true);
136 136 grid->addWidget(zoomCheckBox, grid->rowCount(), 0);
137 137
138 138 QCheckBox *aliasCheckBox = new QCheckBox("Anti-alias");
139 139 connect(aliasCheckBox, SIGNAL(toggled(bool)), this, SLOT(antiAliasToggled(bool)));
140 140 aliasCheckBox->setChecked(false);
141 141 grid->addWidget(aliasCheckBox, grid->rowCount(), 0);
142 142 }
143 143
144 144 void MainWidget::antiAliasToggled(bool enabled)
145 145 {
146 146 m_chartView->setRenderHint(QPainter::Antialiasing, enabled);
147 147 }
148 148
149 149 void MainWidget::addSeries()
150 150 {
151 151 if (!m_addSerieDialog) {
152 152 m_addSerieDialog = new DataSerieDialog(this);
153 153 connect(m_addSerieDialog, SIGNAL(accepted(QString, int, int, QString, bool)),
154 154 this, SLOT(addSeries(QString, int, int, QString, bool)));
155 155 }
156 156 m_addSerieDialog->exec();
157 157 }
158 158
159 159 QList<RealList> MainWidget::generateTestData(int columnCount, int rowCount, QString dataCharacteristics)
160 160 {
161 161 // TODO: dataCharacteristics
162 162 QList<RealList> testData;
163 163 for (int j(0); j < columnCount; j++) {
164 164 QList <qreal> newColumn;
165 165 for (int i(0); i < rowCount; i++) {
166 166 if (dataCharacteristics == "Sin") {
167 167 newColumn.append(abs(sin(3.14159265358979 / 50 * i) * 100));
168 168 } else if (dataCharacteristics == "Sin + random") {
169 169 newColumn.append(abs(sin(3.14159265358979 / 50 * i) * 100) + (rand() % 5));
170 170 } else if (dataCharacteristics == "Random") {
171 171 newColumn.append(rand() % 5);
172 172 } else if (dataCharacteristics == "Linear") {
173 173 //newColumn.append(i * (j + 1.0));
174 174 // TODO: temporary hack to make pie work; prevent zero values:
175 175 newColumn.append(i * (j + 1.0) + 0.1);
176 176 } else { // "constant"
177 177 newColumn.append((j + 1.0));
178 178 }
179 179 }
180 180 testData.append(newColumn);
181 181 }
182 182 return testData;
183 183 }
184 184
185 185 QStringList MainWidget::generateLabels(int count)
186 186 {
187 187 QStringList result;
188 188 for (int i(0); i < count; i++)
189 189 result.append("label" + QString::number(i));
190 190 return result;
191 191 }
192 192
193 193 void MainWidget::addSeries(QString seriesName, int columnCount, int rowCount, QString dataCharacteristics, bool labelsEnabled)
194 194 {
195 195 qDebug() << "addSeries: " << seriesName
196 196 << " columnCount: " << columnCount
197 197 << " rowCount: " << rowCount
198 198 << " dataCharacteristics: " << dataCharacteristics
199 199 << " labels enabled: " << labelsEnabled;
200 200 m_defaultSeriesName = seriesName;
201 201
202 202 QList<RealList> data = generateTestData(columnCount, rowCount, dataCharacteristics);
203 203
204 204 // Line series and scatter series use similar data
205 205 if (seriesName == "Line") {
206 206 for (int j(0); j < data.count(); j ++) {
207 207 QList<qreal> column = data.at(j);
208 208 QLineSeries *series = new QLineSeries();
209 209 for (int i(0); i < column.count(); i++) {
210 210 series->add(i, column.at(i));
211 211 }
212 212 m_chartView->addSeries(series);
213 213 setCurrentSeries(series);
214 214 }
215 215 } if (seriesName == "Area") {
216 216 // TODO: lower series for the area?
217 217 for (int j(0); j < data.count(); j ++) {
218 218 QList<qreal> column = data.at(j);
219 219 QLineSeries *lineSeries = new QLineSeries();
220 220 for (int i(0); i < column.count(); i++) {
221 221 lineSeries->add(i, column.at(i));
222 222 }
223 223 QAreaSeries *areaSeries = new QAreaSeries(lineSeries);
224 224 m_chartView->addSeries(areaSeries);
225 225 setCurrentSeries(areaSeries);
226 226 }
227 227 } else if (seriesName == "Scatter") {
228 228 for (int j(0); j < data.count(); j++) {
229 229 QList<qreal> column = data.at(j);
230 230 QScatterSeries *series = new QScatterSeries();
231 231 for (int i(0); i < column.count(); i++) {
232 232 (*series) << QPointF(i, column.at(i));
233 233 }
234 234 m_chartView->addSeries(series);
235 235 setCurrentSeries(series);
236 236 }
237 237 } else if (seriesName == "Pie") {
238 238 QStringList labels = generateLabels(rowCount);
239 239 for (int j(0); j < data.count(); j++) {
240 240 QPieSeries *series = new QPieSeries();
241 241 QList<qreal> column = data.at(j);
242 242 for (int i(0); i < column.count(); i++) {
243 243 series->add(column.at(i), labels.at(i));
244 244 }
245 245 m_chartView->addSeries(series);
246 246 setCurrentSeries(series);
247 247 }
248 248 } else if (seriesName == "Bar"
249 249 || seriesName == "Stacked bar"
250 250 || seriesName == "Percent bar") {
251 251 QStringList category;
252 252 QStringList labels = generateLabels(rowCount);
253 253 foreach(QString label, labels)
254 254 category << label;
255 255 QBarSeries* series = 0;
256 256 if (seriesName == "Bar")
257 257 series = new QBarSeries(category, this);
258 258 else if (seriesName == "Stacked bar")
259 259 series = new QStackedBarSeries(category, this);
260 260 else
261 261 series = new QPercentBarSeries(category, this);
262 262
263 263 for (int j(0); j < data.count(); j++) {
264 264 QList<qreal> column = data.at(j);
265 265 QBarSet *set = new QBarSet("set" + QString::number(j));
266 266 for (int i(0); i < column.count(); i++) {
267 267 *set << column.at(i);
268 268 }
269 269 series->addBarSet(set);
270 270 }
271 271
272 272 // TODO: new implementation of setFloatingValuesEnabled with signals
273 273 //series->setFloatingValuesEnabled(true);
274 274 series->setToolTipEnabled(true);
275 series->setSeparatorsEnabled(false);
275 series->setSeparatorsVisible(false);
276 276 m_chartView->addSeries(series);
277 277 setCurrentSeries(series);
278 278 } else if (seriesName == "Spline") {
279 279 for (int j(0); j < data.count(); j ++) {
280 280 QList<qreal> column = data.at(j);
281 281 QSplineSeries *series = new QSplineSeries();
282 282 for (int i(0); i < column.count(); i++) {
283 283 series->add(i, column.at(i));
284 284 }
285 285 m_chartView->addSeries(series);
286 286 setCurrentSeries(series);
287 287 }
288 288
289 289 // TODO: area
290 290 }
291 291 }
292 292
293 293 void MainWidget::setCurrentSeries(QSeries *series)
294 294 {
295 295 if (series) {
296 296 m_currentSeries = series;
297 297 switch (m_currentSeries->type()) {
298 298 case QSeries::SeriesTypeLine:
299 299 break;
300 300 case QSeries::SeriesTypeScatter:
301 301 break;
302 302 case QSeries::SeriesTypePie:
303 303 break;
304 304 case QSeries::SeriesTypeBar:
305 305 qDebug() << "setCurrentSeries (bar)";
306 306 break;
307 307 case QSeries::SeriesTypeStackedBar:
308 308 qDebug() << "setCurrentSeries (Stackedbar)";
309 309 break;
310 310 case QSeries::SeriesTypePercentBar:
311 311 qDebug() << "setCurrentSeries (Percentbar)";
312 312 break;
313 313 case QSeries::SeriesTypeSpline:
314 314 break;
315 315 default:
316 316 Q_ASSERT(false);
317 317 break;
318 318 }
319 319 }
320 320 }
321 321
322 322 void MainWidget::backgroundChanged(int itemIndex)
323 323 {
324 324 qDebug() << "backgroundChanged: " << itemIndex;
325 325 }
326 326
327 327 void MainWidget::autoScaleChanged(int value)
328 328 {
329 329 if (value) {
330 330 // TODO: enable auto scaling
331 331 } else {
332 332 // TODO: set scaling manually (and disable auto scaling)
333 333 }
334 334
335 335 m_xMinSpin->setEnabled(!value);
336 336 m_xMaxSpin->setEnabled(!value);
337 337 m_yMinSpin->setEnabled(!value);
338 338 m_yMaxSpin->setEnabled(!value);
339 339 }
340 340
341 341 void MainWidget::xMinChanged(int value)
342 342 {
343 343 qDebug() << "xMinChanged: " << value;
344 344 }
345 345
346 346 void MainWidget::xMaxChanged(int value)
347 347 {
348 348 qDebug() << "xMaxChanged: " << value;
349 349 }
350 350
351 351 void MainWidget::yMinChanged(int value)
352 352 {
353 353 qDebug() << "yMinChanged: " << value;
354 354 }
355 355
356 356 void MainWidget::yMaxChanged(int value)
357 357 {
358 358 qDebug() << "yMaxChanged: " << value;
359 359 }
360 360
361 361 void MainWidget::changeChartTheme(int themeIndex)
362 362 {
363 363 qDebug() << "changeChartTheme: " << themeIndex;
364 364 m_chartView->setChartTheme((QChart::ChartTheme) themeIndex);
365 365 //TODO: remove this hack. This is just to make it so that theme change is seen immediately.
366 366 QSize s = size();
367 367 s.setWidth(s.width()+1);
368 368 resize(s);
369 369 }
General Comments 0
You need to be logged in to leave comments. Login now