@@ -0,0 +1,113 | |||
|
1 | #include <QtGui/QApplication> | |
|
2 | #include <QMainWindow> | |
|
3 | #include <qchartglobal.h> | |
|
4 | #include <qchartview.h> | |
|
5 | #include <qpieseries.h> | |
|
6 | #include <qpieslice.h> | |
|
7 | #include <QTime> | |
|
8 | ||
|
9 | QTCOMMERCIALCHART_USE_NAMESPACE | |
|
10 | ||
|
11 | class DrilldownSlice : public QPieSlice | |
|
12 | { | |
|
13 | Q_OBJECT | |
|
14 | ||
|
15 | public: | |
|
16 | DrilldownSlice(qreal value, QString prefix, QSeries* drilldownSeries) | |
|
17 | :m_drilldownSeries(drilldownSeries), | |
|
18 | m_prefix(prefix) | |
|
19 | { | |
|
20 | setValue(value); | |
|
21 | setLabelVisible(true); | |
|
22 | updateLabel(); | |
|
23 | connect(this, SIGNAL(changed()), this, SLOT(updateLabel())); | |
|
24 | } | |
|
25 | ||
|
26 | QSeries* drilldownSeries() const { return m_drilldownSeries; } | |
|
27 | ||
|
28 | public Q_SLOTS: | |
|
29 | void updateLabel() | |
|
30 | { | |
|
31 | QString label = m_prefix; | |
|
32 | label += " " + QString::number(this->value())+ "e ("; | |
|
33 | label += QString::number(this->percentage()*100, 'f', 1) + "%)"; | |
|
34 | setLabel(label); | |
|
35 | } | |
|
36 | ||
|
37 | private: | |
|
38 | QSeries* m_drilldownSeries; | |
|
39 | QString m_prefix; | |
|
40 | }; | |
|
41 | ||
|
42 | class DrilldownChart : public QChartView | |
|
43 | { | |
|
44 | Q_OBJECT | |
|
45 | public: | |
|
46 | explicit DrilldownChart(QWidget *parent = 0):QChartView(parent), m_currentSeries(0) {} | |
|
47 | ||
|
48 | void changeSeries(QSeries* series) | |
|
49 | { | |
|
50 | if (m_currentSeries) | |
|
51 | removeSeries(m_currentSeries); | |
|
52 | m_currentSeries = series; | |
|
53 | addSeries(series); | |
|
54 | setChartTitle(series->title()); | |
|
55 | } | |
|
56 | ||
|
57 | public Q_SLOTS: | |
|
58 | void handleSliceClicked(QPieSlice* slice) | |
|
59 | { | |
|
60 | DrilldownSlice* drilldownSlice = static_cast<DrilldownSlice*>(slice); | |
|
61 | changeSeries(drilldownSlice->drilldownSeries()); | |
|
62 | } | |
|
63 | ||
|
64 | private: | |
|
65 | QSeries* m_currentSeries; | |
|
66 | }; | |
|
67 | ||
|
68 | int main(int argc, char *argv[]) | |
|
69 | { | |
|
70 | QApplication a(argc, argv); | |
|
71 | ||
|
72 | qsrand(QTime(0,0,0).secsTo(QTime::currentTime())); | |
|
73 | ||
|
74 | QMainWindow window; | |
|
75 | ||
|
76 | DrilldownChart* drilldownChart = new DrilldownChart(&window); | |
|
77 | drilldownChart->setRenderHint(QPainter::Antialiasing); | |
|
78 | drilldownChart->setChartTheme(QChart::ChartThemeVanilla); | |
|
79 | ||
|
80 | QPieSeries* yearSeries = new QPieSeries(drilldownChart); | |
|
81 | yearSeries->setTitle("Sales by year - All"); | |
|
82 | yearSeries->setHoverHighlighting(); | |
|
83 | ||
|
84 | QList<QString> months; | |
|
85 | months << "Jan" << "Feb" << "Mar" << "Apr" << "May" << "Jun" << "Jul" << "Aug" << "Sep" << "Oct" << "Nov" << "Dec"; | |
|
86 | QList<QString> names; | |
|
87 | names << "Jane" << "John" << "Axel" << "Mary" << "Samantha" << "Bob"; | |
|
88 | ||
|
89 | foreach (QString name, names) { | |
|
90 | QPieSeries* series = new QPieSeries(drilldownChart); | |
|
91 | series->setTitle("Sales by month - " + name); | |
|
92 | series->setHoverHighlighting(); | |
|
93 | ||
|
94 | foreach (QString month, months) | |
|
95 | *series << new DrilldownSlice(qrand() % 1000, month, yearSeries); | |
|
96 | ||
|
97 | QObject::connect(series, SIGNAL(clicked(QPieSlice*)), drilldownChart, SLOT(handleSliceClicked(QPieSlice*))); | |
|
98 | ||
|
99 | *yearSeries << new DrilldownSlice(series->total(), name, series); | |
|
100 | } | |
|
101 | ||
|
102 | QObject::connect(yearSeries, SIGNAL(clicked(QPieSlice*)), drilldownChart, SLOT(handleSliceClicked(QPieSlice*))); | |
|
103 | ||
|
104 | drilldownChart->changeSeries(yearSeries); | |
|
105 | ||
|
106 | window.setCentralWidget(drilldownChart); | |
|
107 | window.resize(600, 600); | |
|
108 | window.show(); | |
|
109 | ||
|
110 | return a.exec(); | |
|
111 | } | |
|
112 | ||
|
113 | #include "main.moc" |
@@ -0,0 +1,9 | |||
|
1 | !include( ../example.pri ) { | |
|
2 | error( "Couldn't find the example.pri file!" ) | |
|
3 | } | |
|
4 | TARGET = piechartdrilldown | |
|
5 | SOURCES += main.cpp | |
|
6 | HEADERS += | |
|
7 | ||
|
8 | ||
|
9 | MOC_DIR = $$PWD/moc |
@@ -0,0 +1,17 | |||
|
1 | #include "barcategory_p.h" | |
|
2 | ||
|
3 | QTCOMMERCIALCHART_BEGIN_NAMESPACE | |
|
4 | BarCategory::BarCategory(QString name, QObject *parent) : | |
|
5 | QObject(parent) | |
|
6 | ,mName(name) | |
|
7 | { | |
|
8 | } | |
|
9 | ||
|
10 | void BarCategory::barRightClickEvent() | |
|
11 | { | |
|
12 | // TODO: | |
|
13 | emit rightClicked(mName); | |
|
14 | } | |
|
15 | ||
|
16 | #include "moc_barcategory_p.cpp" | |
|
17 | QTCOMMERCIALCHART_END_NAMESPACE |
@@ -0,0 +1,26 | |||
|
1 | #ifndef BARCATEGORY_P_H | |
|
2 | #define BARCATEGORY_P_H | |
|
3 | ||
|
4 | #include <QObject> | |
|
5 | #include <qchartglobal.h> | |
|
6 | ||
|
7 | QTCOMMERCIALCHART_BEGIN_NAMESPACE | |
|
8 | // Event handler for bar category | |
|
9 | class BarCategory : public QObject | |
|
10 | { | |
|
11 | Q_OBJECT | |
|
12 | public: | |
|
13 | explicit BarCategory(QString name, QObject *parent = 0); | |
|
14 | ||
|
15 | signals: | |
|
16 | void rightClicked(QString name); // "We want something to happen that involves this category" | |
|
17 | ||
|
18 | public slots: | |
|
19 | void barRightClickEvent(); | |
|
20 | ||
|
21 | private: | |
|
22 | QString mName; | |
|
23 | }; | |
|
24 | ||
|
25 | QTCOMMERCIALCHART_END_NAMESPACE | |
|
26 | #endif // BARCATEGORY_P_H |
@@ -7,6 +7,7 SUBDIRS += linechart \ | |||
|
7 | 7 | percentbarchart \ |
|
8 | 8 | scatter \ |
|
9 | 9 | piechart \ |
|
10 | piechartdrilldown \ | |
|
10 | 11 | dynamiclinechart \ |
|
11 | 12 | axischart \ |
|
12 | 13 | multichart \ |
@@ -8,7 +8,7 QTCOMMERCIALCHART_BEGIN_NAMESPACE | |||
|
8 | 8 | Bar::Bar(QGraphicsItem *parent) |
|
9 | 9 | : QGraphicsObject(parent) |
|
10 | 10 | { |
|
11 | setAcceptedMouseButtons(Qt::LeftButton); | |
|
11 | setAcceptedMouseButtons(Qt::LeftButton|Qt::RightButton); | |
|
12 | 12 | setAcceptHoverEvents(true); |
|
13 | 13 | } |
|
14 | 14 | |
@@ -64,9 +64,13 QRectF Bar::boundingRect() const | |||
|
64 | 64 | return r; |
|
65 | 65 | } |
|
66 | 66 | |
|
67 |
void Bar::mousePressEvent(QGraphicsSceneMouseEvent* |
|
|
67 | void Bar::mousePressEvent(QGraphicsSceneMouseEvent* event) | |
|
68 | 68 | { |
|
69 | emit clicked(); | |
|
69 | if (event->button() == Qt::LeftButton) { | |
|
70 | emit clicked(); | |
|
71 | } else if (event->button() == Qt::RightButton) { | |
|
72 | emit rightClicked(); | |
|
73 | } | |
|
70 | 74 | } |
|
71 | 75 | |
|
72 | 76 | void Bar::hoverEnterEvent(QGraphicsSceneHoverEvent* event) |
@@ -34,6 +34,7 public: | |||
|
34 | 34 | |
|
35 | 35 | Q_SIGNALS: |
|
36 | 36 | void clicked(); |
|
37 | void rightClicked(); | |
|
37 | 38 | void hoverEntered(QPoint pos); |
|
38 | 39 | void hoverLeaved(); |
|
39 | 40 | |
@@ -43,7 +44,6 private: | |||
|
43 | 44 | qreal mWidth; |
|
44 | 45 | qreal mXpos; |
|
45 | 46 | qreal mYpos; |
|
46 | QColor mColor; | |
|
47 | 47 | |
|
48 | 48 | QBrush mBrush; |
|
49 | 49 | QPen mPen; |
@@ -14,7 +14,8 SOURCES += \ | |||
|
14 | 14 | $$PWD/qstackedbarseries.cpp \ |
|
15 | 15 | $$PWD/separator.cpp \ |
|
16 | 16 | $$PWD/stackedbarpresenter.cpp \ |
|
17 | $$PWD/barvalue.cpp | |
|
17 | $$PWD/barvalue.cpp \ | |
|
18 | $$PWD/barcategory.cpp | |
|
18 | 19 | |
|
19 | 20 | PRIVATE_HEADERS += \ |
|
20 | 21 | $$PWD/bar_p.h \ |
@@ -25,12 +26,12 PRIVATE_HEADERS += \ | |||
|
25 | 26 | $$PWD/percentbarpresenter_p.h \ |
|
26 | 27 | $$PWD/separator_p.h \ |
|
27 | 28 | $$PWD/stackedbarpresenter_p.h \ |
|
28 | $$PWD/barvalue_p.h | |
|
29 | $$PWD/barvalue_p.h \ | |
|
30 | $$PWD/barcategory_p.h | |
|
29 | 31 | |
|
30 | 32 | PUBLIC_HEADERS += \ |
|
31 | 33 | $$PWD/qbarseries.h \ |
|
32 | 34 | $$PWD/qbarset.h \ |
|
33 | 35 | $$PWD/qpercentbarseries.h \ |
|
34 | 36 | $$PWD/qstackedbarseries.h |
|
35 | ||
|
36 | 37 |
@@ -2,6 +2,7 | |||
|
2 | 2 | #include <QVector> |
|
3 | 3 | #include <QDebug> |
|
4 | 4 | #include "barchartmodel_p.h" |
|
5 | #include "barcategory_p.h" | |
|
5 | 6 | #include "qbarset.h" |
|
6 | 7 | |
|
7 | 8 | QTCOMMERCIALCHART_BEGIN_NAMESPACE |
@@ -10,6 +11,10 BarChartModel::BarChartModel(QStringList categories, QObject *parent) : | |||
|
10 | 11 | QObject(parent) |
|
11 | 12 | ,mCategory(categories) |
|
12 | 13 | { |
|
14 | for (int i=0; i<mCategory.count(); i++) { | |
|
15 | BarCategory* cat = new BarCategory(mCategory.at(i), this); | |
|
16 | mCategoryObjects.append(cat); | |
|
17 | } | |
|
13 | 18 | } |
|
14 | 19 | |
|
15 | 20 | QStringList BarChartModel::category() |
@@ -162,11 +167,16 qreal BarChartModel::maxCategorySum() | |||
|
162 | 167 | return max; |
|
163 | 168 | } |
|
164 | 169 | |
|
165 |
QString BarChartModel:: |
|
|
170 | QString BarChartModel::categoryName(int category) | |
|
166 | 171 | { |
|
167 | 172 | return mCategory.at(category); |
|
168 | 173 | } |
|
169 | 174 | |
|
175 | BarCategory* BarChartModel::categoryObject(int category) | |
|
176 | { | |
|
177 | return mCategoryObjects.at(category); | |
|
178 | } | |
|
179 | ||
|
170 | 180 | #include "moc_barchartmodel_p.cpp" |
|
171 | 181 | |
|
172 | 182 | QTCOMMERCIALCHART_END_NAMESPACE |
@@ -12,6 +12,7 QTCOMMERCIALCHART_BEGIN_NAMESPACE | |||
|
12 | 12 | // TODO: Implement as QAbstractItemModel? |
|
13 | 13 | |
|
14 | 14 | class QBarSet; |
|
15 | class BarCategory; | |
|
15 | 16 | |
|
16 | 17 | class BarChartModel : public QObject //, public QAbstractItemModel |
|
17 | 18 | { |
@@ -38,7 +39,8 public: | |||
|
38 | 39 | qreal categorySum(int category); |
|
39 | 40 | qreal maxCategorySum(); // returns maximum sum of sets in all categories. |
|
40 | 41 | |
|
41 |
QString |
|
|
42 | QString categoryName(int category); | |
|
43 | BarCategory* categoryObject(int category); | |
|
42 | 44 | |
|
43 | 45 | signals: |
|
44 | 46 | void modelUpdated(); |
@@ -49,6 +51,7 private: | |||
|
49 | 51 | |
|
50 | 52 | QList<QBarSet*> mDataModel; |
|
51 | 53 | QStringList mCategory; |
|
54 | QList<BarCategory*> mCategoryObjects; | |
|
52 | 55 | |
|
53 | 56 | int mCurrentSet; |
|
54 | 57 |
@@ -3,6 +3,7 | |||
|
3 | 3 | #include "barvalue_p.h" |
|
4 | 4 | #include "barlabel_p.h" |
|
5 | 5 | #include "separator_p.h" |
|
6 | #include "barcategory_p.h" | |
|
6 | 7 | #include "qbarset.h" |
|
7 | 8 | #include "qbarseries.h" |
|
8 | 9 | #include <QDebug> |
@@ -56,7 +57,7 void BarPresenterBase::setBarWidth( int w ) | |||
|
56 | 57 | void BarPresenterBase::dataChanged() |
|
57 | 58 | { |
|
58 | 59 | // TODO: performance optimizations. Do we really need to delete and create items every time data is changed or can we reuse them? |
|
59 | qDebug() << "datachanged"; | |
|
60 | // qDebug() << "datachanged"; | |
|
60 | 61 | // Delete old bars |
|
61 | 62 | foreach (QGraphicsItem* item, childItems()) { |
|
62 | 63 | delete item; |
@@ -69,14 +70,16 void BarPresenterBase::dataChanged() | |||
|
69 | 70 | |
|
70 | 71 | // Create new graphic items for bars |
|
71 | 72 | for (int c=0; c<mSeries->categoryCount(); c++) { |
|
73 | BarCategory *category = mSeries->categoryObject(c); | |
|
72 | 74 | for (int s=0; s<mSeries->barsetCount(); s++) { |
|
73 | 75 | QBarSet *set = mSeries->barsetAt(s); |
|
74 | 76 | Bar *bar = new Bar(this); |
|
75 | 77 | childItems().append(bar); |
|
76 | 78 | mBars.append(bar); |
|
77 | connect(bar,SIGNAL(clicked()),set,SLOT(barClicked())); | |
|
78 |
connect(bar,SIGNAL( |
|
|
79 |
connect(bar,SIGNAL(hover |
|
|
79 | connect(bar,SIGNAL(clicked()),set,SLOT(barClickedEvent())); | |
|
80 | connect(bar,SIGNAL(rightClicked()),category,SLOT(barRightClickEvent())); | |
|
81 | connect(bar,SIGNAL(hoverEntered(QPoint)),set,SLOT(barHoverEnterEvent(QPoint))); | |
|
82 | connect(bar,SIGNAL(hoverLeaved()),set,SLOT(barHoverLeaveEvent())); | |
|
80 | 83 | } |
|
81 | 84 | } |
|
82 | 85 | |
@@ -84,7 +87,7 void BarPresenterBase::dataChanged() | |||
|
84 | 87 | int count = mSeries->categoryCount(); |
|
85 | 88 | for (int i=0; i<count; i++) { |
|
86 | 89 | BarLabel* label = new BarLabel(this); |
|
87 |
label->set(mSeries-> |
|
|
90 | label->set(mSeries->categoryName(i)); | |
|
88 | 91 | childItems().append(label); |
|
89 | 92 | mLabels.append(label); |
|
90 | 93 | } |
@@ -2,7 +2,7 | |||
|
2 | 2 | #include "qbarseries.h" |
|
3 | 3 | #include "qbarset.h" |
|
4 | 4 | #include "barchartmodel_p.h" |
|
5 | ||
|
5 | #include "barcategory_p.h" | |
|
6 | 6 | |
|
7 | 7 | QTCOMMERCIALCHART_BEGIN_NAMESPACE |
|
8 | 8 | |
@@ -53,6 +53,10 QBarSeries::QBarSeries(QStringList categories, QObject *parent) | |||
|
53 | 53 | : QSeries(parent) |
|
54 | 54 | ,mModel(new BarChartModel(categories, this)) |
|
55 | 55 | { |
|
56 | for (int i=0; i<mModel->categoryCount(); i++) { | |
|
57 | BarCategory *categoryObject = mModel->categoryObject(i); | |
|
58 | connect(categoryObject, SIGNAL(rightClicked(QString)), this, SIGNAL(categoryRightClicked(QString))); | |
|
59 | } | |
|
56 | 60 | } |
|
57 | 61 | |
|
58 | 62 | /*! |
@@ -114,9 +118,9 QList<QSeries::Legend> QBarSeries::legend() | |||
|
114 | 118 | /*! |
|
115 | 119 | \internal \a category |
|
116 | 120 | */ |
|
117 |
QString QBarSeries:: |
|
|
121 | QString QBarSeries::categoryName(int category) | |
|
118 | 122 | { |
|
119 |
return mModel-> |
|
|
123 | return mModel->categoryName(category); | |
|
120 | 124 | } |
|
121 | 125 | |
|
122 | 126 | /*! |
@@ -225,6 +229,12 BarChartModel& QBarSeries::model() | |||
|
225 | 229 | return *mModel; |
|
226 | 230 | } |
|
227 | 231 | |
|
232 | BarCategory* QBarSeries::categoryObject(int category) | |
|
233 | { | |
|
234 | return mModel->categoryObject(category); | |
|
235 | } | |
|
236 | ||
|
237 | ||
|
228 | 238 | #include "moc_qbarseries.cpp" |
|
229 | 239 | |
|
230 | 240 | QTCOMMERCIALCHART_END_NAMESPACE |
@@ -8,6 +8,7 QTCOMMERCIALCHART_BEGIN_NAMESPACE | |||
|
8 | 8 | |
|
9 | 9 | class QBarSet; |
|
10 | 10 | class BarChartModel; |
|
11 | class BarCategory; | |
|
11 | 12 | |
|
12 | 13 | // Container for series |
|
13 | 14 | class QTCOMMERCIALCHART_EXPORT QBarSeries : public QSeries |
@@ -29,8 +30,8 public: | |||
|
29 | 30 | // TODO: Functions below this are not part of api and will be moved |
|
30 | 31 | // to private implementation, when we start using it |
|
31 | 32 | // TODO: TO PIMPL ---> |
|
32 |
QBarSet |
|
|
33 |
QString |
|
|
33 | QBarSet* barsetAt(int index); | |
|
34 | QString categoryName(int category); | |
|
34 | 35 | qreal min(); |
|
35 | 36 | qreal max(); |
|
36 | 37 | qreal valueAt(int set, int category); |
@@ -38,10 +39,12 public: | |||
|
38 | 39 | qreal categorySum(int category); |
|
39 | 40 | qreal maxCategorySum(); |
|
40 | 41 | BarChartModel& model(); |
|
42 | BarCategory* categoryObject(int category); | |
|
41 | 43 | // <--- TO PIMPL |
|
42 | 44 | |
|
43 | 45 | signals: |
|
44 | 46 | void changed(int index); |
|
47 | void categoryRightClicked(QString category); | |
|
45 | 48 | |
|
46 | 49 | // TODO: internal signals, these to private implementation. |
|
47 | 50 | // TODO: TO PIMPL ---> |
@@ -133,9 +133,8 QBrush QBarSet::brush() | |||
|
133 | 133 | /*! |
|
134 | 134 | \internal |
|
135 | 135 | */ |
|
136 | void QBarSet::barClicked() | |
|
136 | void QBarSet::barClickedEvent() | |
|
137 | 137 | { |
|
138 | // qDebug() << "QBarset::barClicked" << this; | |
|
139 | 138 | // Some bar of this set has been clicked |
|
140 | 139 | // TODO: What happens then? |
|
141 | 140 | emit clicked(); // Notify that set has been clicked |
@@ -144,7 +143,7 void QBarSet::barClicked() | |||
|
144 | 143 | /*! |
|
145 | 144 | \internal \a pos |
|
146 | 145 | */ |
|
147 |
void QBarSet::barHoverEnter |
|
|
146 | void QBarSet::barHoverEnterEvent(QPoint pos) | |
|
148 | 147 | { |
|
149 | 148 | emit showToolTip(pos, mName); |
|
150 | 149 | emit hoverEnter(pos); |
@@ -153,12 +152,8 void QBarSet::barHoverEntered(QPoint pos) | |||
|
153 | 152 | /*! |
|
154 | 153 | \internal |
|
155 | 154 | */ |
|
156 |
void QBarSet::barHoverLeave |
|
|
155 | void QBarSet::barHoverLeaveEvent() | |
|
157 | 156 | { |
|
158 | // qDebug() << "QBarset::barHoverLeaved" << this; | |
|
159 | // if (mToolTipEnabled) { | |
|
160 | // TODO: do what? | |
|
161 | // } | |
|
162 | 157 | // Emit signal to user of charts |
|
163 | 158 | emit hoverLeave(); |
|
164 | 159 | } |
@@ -41,9 +41,9 Q_SIGNALS: | |||
|
41 | 41 | public Q_SLOTS: |
|
42 | 42 | // These are for internal communication |
|
43 | 43 | // TODO: TO PIMPL ---> |
|
44 | void barClicked(); | |
|
45 |
void barHoverEnter |
|
|
46 |
void barHoverLeave |
|
|
44 | void barClickedEvent(); | |
|
45 | void barHoverEnterEvent(QPoint pos); | |
|
46 | void barHoverLeaveEvent(); | |
|
47 | 47 | // <--- TO PIMPL |
|
48 | 48 | |
|
49 | 49 | private: |
@@ -149,7 +149,7 void ChartDataSet::addSeries(QSeries* series, QChartAxis *axisY) | |||
|
149 | 149 | m_domainMap.replace(axisY,domain); |
|
150 | 150 | m_seriesMap.insert(axisY,series); |
|
151 | 151 | emit seriesAdded(series); |
|
152 | setDomain(m_domainIndex); | |
|
152 | setDomain(m_domainIndex,axisY); | |
|
153 | 153 | |
|
154 | 154 | } |
|
155 | 155 | |
@@ -244,6 +244,27 void ChartDataSet::setDomain(int index) | |||
|
244 | 244 | emit axisRangeChanged(axisX(),labels); |
|
245 | 245 | } |
|
246 | 246 | |
|
247 | void ChartDataSet::setDomain(int index,QChartAxis* axis) | |
|
248 | { | |
|
249 | int i = m_domainMap.count(axis) - index -1; | |
|
250 | Q_ASSERT(i>=0); | |
|
251 | Domain domain = m_domainMap.values(axis).at(i); | |
|
252 | { | |
|
253 | QStringList labels = createLabels(axis,domain.m_minY,domain.m_maxY); | |
|
254 | QList<QSeries*> seriesList = m_seriesMap.values(axis); | |
|
255 | foreach(QSeries* series, seriesList) { | |
|
256 | emit seriesDomainChanged(series,domain); | |
|
257 | } | |
|
258 | axis->updateRange(domain.m_minY,domain.m_maxY); | |
|
259 | emit axisRangeChanged(axis,labels); | |
|
260 | } | |
|
261 | ||
|
262 | QStringList labels = createLabels(axisX(),domain.m_minX,domain.m_maxX); | |
|
263 | axisX()->updateRange(domain.m_minX,domain.m_maxY); | |
|
264 | emit axisRangeChanged(axisX(),labels); | |
|
265 | } | |
|
266 | ||
|
267 | ||
|
247 | 268 | void ChartDataSet::clearDomains(int toIndex) |
|
248 | 269 | { |
|
249 | 270 | Q_ASSERT(toIndex>=0); |
@@ -342,6 +363,8 void ChartDataSet::handleRangeChanged(QChartAxis* axis) | |||
|
342 | 363 | m_domainMap.replace(axis,domain); |
|
343 | 364 | } |
|
344 | 365 | |
|
366 | setDomain(m_domainIndex); | |
|
367 | ||
|
345 | 368 | } |
|
346 | 369 | else { |
|
347 | 370 | |
@@ -356,9 +379,11 void ChartDataSet::handleRangeChanged(QChartAxis* axis) | |||
|
356 | 379 | |
|
357 | 380 | for(int j=domains.size()-1; j>=0;j--) |
|
358 | 381 | m_domainMap.insert(axis,domains.at(j)); |
|
382 | ||
|
383 | setDomain(m_domainIndex,axis); | |
|
359 | 384 | } |
|
360 | 385 | |
|
361 | setDomain(m_domainIndex); | |
|
386 | ||
|
362 | 387 | } |
|
363 | 388 | |
|
364 | 389 | void ChartDataSet::handleTickChanged(QChartAxis* axis) |
@@ -26,6 +26,7 public: | |||
|
26 | 26 | const Domain domain(QChartAxis *axisY) const; |
|
27 | 27 | int domainIndex() const {return m_domainIndex;} |
|
28 | 28 | void setDomain(int index); |
|
29 | void setDomain(int index,QChartAxis* axis); | |
|
29 | 30 | |
|
30 | 31 | QChartAxis* axisX() const { return m_axisX;}; |
|
31 | 32 | QChartAxis* axisY(QSeries* series = 0) const; |
@@ -123,12 +123,22 void PiePresenter::updateGeometry() | |||
|
123 | 123 | foreach (QPieSlice* s, m_series->m_slices) { |
|
124 | 124 | |
|
125 | 125 | // calculate the farthest point in the slice from the pie center |
|
126 | ||
|
127 | // the arm | |
|
126 | 128 | qreal centerAngle = s->m_startAngle + (s->m_angleSpan / 2); |
|
127 | qreal len = pieRadius + s->labelArmLength() + s->explodeDistance(); | |
|
129 | qreal len = pieRadius + PIESLICE_LABEL_GAP + s->labelArmLength() + s->explodeDistance(); | |
|
128 | 130 | QPointF dp(qSin(centerAngle*(PI/180)) * len, -qCos(centerAngle*(PI/180)) * len); |
|
129 | 131 | QPointF p = pieRect.center() + dp; |
|
130 | 132 | |
|
131 |
// |
|
|
133 | // the label text | |
|
134 | QFontMetricsF fm(s->labelFont()); | |
|
135 | QRectF labelRect = fm.boundingRect(s->label()); | |
|
136 | if (centerAngle < 90 || centerAngle > 270) | |
|
137 | p += QPointF(0, -labelRect.height()); | |
|
138 | if (centerAngle < 180) | |
|
139 | p += QPointF(labelRect.width(), 0); | |
|
140 | else | |
|
141 | p += QPointF(-labelRect.width(), 0); | |
|
132 | 142 | |
|
133 | 143 | // calculate how much the radius must get smaller to fit that point in the base rectangle |
|
134 | 144 | qreal dt = m_rect.top() - p.y(); |
@@ -100,7 +100,7 void PieSlice::updateGeometry() | |||
|
100 | 100 | |
|
101 | 101 | // update label position |
|
102 | 102 | qreal radius = rect.height() / 2; |
|
103 |
QPointF edgeCenter = rect.center() + offset(centerAngle, radius + |
|
|
103 | QPointF edgeCenter = rect.center() + offset(centerAngle, radius + PIESLICE_LABEL_GAP); | |
|
104 | 104 | m_slicelabel->setArmStartPoint(edgeCenter); |
|
105 | 105 | m_slicelabel->setArmAngle(centerAngle); |
|
106 | 106 | m_slicelabel->updateGeometry(); |
@@ -9,6 +9,8 | |||
|
9 | 9 | #include <QColor> |
|
10 | 10 | #include <QPen> |
|
11 | 11 | |
|
12 | #define PIESLICE_LABEL_GAP 5 | |
|
13 | ||
|
12 | 14 | QTCOMMERCIALCHART_BEGIN_NAMESPACE |
|
13 | 15 | class PiePresenter; |
|
14 | 16 | class PieSliceLabel; |
@@ -45,9 +45,9 void PieSliceLabel::updateGeometry() | |||
|
45 | 45 | QPointF parm2 = parm1; |
|
46 | 46 | textRect.moveBottomLeft(parm1); |
|
47 | 47 | if (m_armAngle < 180) { // arm swings the other way on the left side |
|
48 |
parm2 += QPointF( |
|
|
48 | parm2 += QPointF(textRect.width(), 0); | |
|
49 | 49 | } else { |
|
50 |
parm2 += QPointF(- |
|
|
50 | parm2 += QPointF(-textRect.width(),0); | |
|
51 | 51 | textRect.moveBottomLeft(parm2); |
|
52 | 52 | } |
|
53 | 53 |
@@ -188,6 +188,16 void QPieSeries::add(QPieSlice* slice) | |||
|
188 | 188 | add(QList<QPieSlice*>() << slice); |
|
189 | 189 | } |
|
190 | 190 | |
|
191 | /*! | |
|
192 | Adds a single \a slice to the series and returns a reference to the series. | |
|
193 | Slice ownership is passed to the series. | |
|
194 | */ | |
|
195 | QPieSeries& QPieSeries::operator << (QPieSlice* slice) | |
|
196 | { | |
|
197 | add(slice); | |
|
198 | return *this; | |
|
199 | } | |
|
200 | ||
|
191 | 201 | |
|
192 | 202 | /*! |
|
193 | 203 | Adds a single slice to the series with give \a value and \a name. |
@@ -348,10 +358,7 void QPieSeries::setClickExplodes(bool enable) | |||
|
348 | 358 | Convenience method for highlighting a slice when user hovers over the slice. |
|
349 | 359 | It changes the slice color to be lighter and shows the label of the slice. |
|
350 | 360 | Set \a enable to true to highlight a slice when user hovers on top of it. |
|
351 | ||
|
352 | \sa QPieSlice::isExploded(), QPieSlice::setExploded() | |
|
353 | 361 | */ |
|
354 | ||
|
355 | 362 | void QPieSeries::setHoverHighlighting(bool enable) |
|
356 | 363 | { |
|
357 | 364 | if (enable) { |
@@ -364,6 +371,16 void QPieSeries::setHoverHighlighting(bool enable) | |||
|
364 | 371 | } |
|
365 | 372 | |
|
366 | 373 | /*! |
|
374 | Returns the sum of all slice values in this series. | |
|
375 | ||
|
376 | \sa QPieSlice::value(), QPieSlice::setValue() | |
|
377 | */ | |
|
378 | qreal QPieSeries::total() const | |
|
379 | { | |
|
380 | return m_total; | |
|
381 | } | |
|
382 | ||
|
383 | /*! | |
|
367 | 384 | \fn void QPieSeries::changed(const QPieSeries::ChangeSet& changeSet) |
|
368 | 385 | |
|
369 | 386 | This signal emitted when something has changed in the series. |
@@ -456,7 +473,6 void QPieSeries::highlightOn(QPieSlice* slice) | |||
|
456 | 473 | Q_ASSERT(slice); |
|
457 | 474 | QColor c = slice->brush().color().lighter(); |
|
458 | 475 | slice->setBrush(c); |
|
459 | slice->setLabelVisible(true); | |
|
460 | 476 | } |
|
461 | 477 | |
|
462 | 478 | void QPieSeries::highlightOff(QPieSlice* slice) |
@@ -464,7 +480,6 void QPieSeries::highlightOff(QPieSlice* slice) | |||
|
464 | 480 | Q_ASSERT(slice); |
|
465 | 481 | QColor c = slice->brush().color().darker(150); |
|
466 | 482 | slice->setBrush(c); |
|
467 | slice->setLabelVisible(false); | |
|
468 | 483 | } |
|
469 | 484 | |
|
470 | 485 | void QPieSeries::updateDerivativeData() |
@@ -480,7 +495,10 void QPieSeries::updateDerivativeData() | |||
|
480 | 495 | m_total += s->value(); |
|
481 | 496 | |
|
482 | 497 | // we must have some values |
|
483 | Q_ASSERT(m_total > 0); // TODO: is this the correct way to handle this? | |
|
498 | if (m_total == 0) { | |
|
499 | qDebug() << "QPieSeries::updateDerivativeData() total == 0"; | |
|
500 | Q_ASSERT(m_total > 0); // TODO: is this the correct way to handle this? | |
|
501 | } | |
|
484 | 502 | |
|
485 | 503 | // update slice attributes |
|
486 | 504 | qreal sliceAngle = m_pieStartAngle; |
@@ -62,6 +62,7 public: | |||
|
62 | 62 | void add(QList<QPieSlice*> slices); |
|
63 | 63 | void add(QPieSlice* slice); |
|
64 | 64 | QPieSlice* add(qreal value, QString name); |
|
65 | QPieSeries& operator << (QPieSlice* slice); | |
|
65 | 66 | void remove(QPieSlice* slice); |
|
66 | 67 | void clear(); |
|
67 | 68 | |
@@ -78,6 +79,8 public: | |||
|
78 | 79 | void setClickExplodes(bool enable = true); |
|
79 | 80 | void setHoverHighlighting(bool enable = true); |
|
80 | 81 | |
|
82 | qreal total() const; | |
|
83 | ||
|
81 | 84 | // TODO: find slices? |
|
82 | 85 | // QList<QPieSlice*> findByValue(qreal value); |
|
83 | 86 | // ... |
@@ -52,6 +52,20 | |||
|
52 | 52 | \brief Returns the legend of the series. If series is empty, empty list is returned. |
|
53 | 53 | */ |
|
54 | 54 | |
|
55 | /*! | |
|
56 | \fn void QSeries::setTitle(QString title) | |
|
57 | \brief Sets a \a title for the series. | |
|
58 | ||
|
59 | This is not used directly by the chart itself. It is up to the user to use this as for example | |
|
60 | chart title. | |
|
61 | \sa QChart::setChartTitle() | |
|
62 | */ | |
|
63 | ||
|
64 | /*! | |
|
65 | \fn QString QSeries::title() | |
|
66 | \brief Returns the title of the series. | |
|
67 | */ | |
|
68 | ||
|
55 | 69 | QTCOMMERCIALCHART_BEGIN_NAMESPACE |
|
56 | 70 | #include "moc_qseries.cpp" |
|
57 | 71 | QTCOMMERCIALCHART_END_NAMESPACE |
@@ -42,6 +42,12 public: | |||
|
42 | 42 | |
|
43 | 43 | // TODO: should this be internal? |
|
44 | 44 | virtual QList<QSeries::Legend> legend() { QList<QSeries::Legend> l; return l; } |
|
45 | ||
|
46 | void setTitle(QString title) { m_title = title; } | |
|
47 | QString title() { return m_title; } | |
|
48 | ||
|
49 | private: | |
|
50 | QString m_title; | |
|
45 | 51 | }; |
|
46 | 52 | |
|
47 | 53 | QTCOMMERCIALCHART_END_NAMESPACE |
@@ -135,69 +135,85 void tst_ChartDataSet::addDomain() | |||
|
135 | 135 | |
|
136 | 136 | void tst_ChartDataSet::addSeries_data() |
|
137 | 137 | { |
|
138 |
QTest::addColumn<int>(" |
|
|
139 |
|
|
|
140 | QTest::newRow("2 series, default axis") << 2 << 0; | |
|
141 |
QTest::newRow("2 |
|
|
142 |
QTest::newRow("2 series, |
|
|
143 |
QTest::newRow(" |
|
|
144 |
QTest::newRow("3 series, |
|
|
145 |
QTest::newRow("3 series, |
|
|
138 | QTest::addColumn<int>("defaultAxisCount"); | |
|
139 | QTest::addColumn<int>("firstAxisCount"); | |
|
140 | QTest::addColumn<int>("secoundAxisCount"); | |
|
141 | QTest::newRow("2 ,1 ,0") << 2 << 1 << 0; | |
|
142 | QTest::newRow("2 series, 2 new axis") << 2 << 0 << 2; | |
|
143 | QTest::newRow("2 series, 1 new axis") << 2 << 0 << 2; | |
|
144 | QTest::newRow("3 series, 3 new axis") << 3 << 0 << 3; | |
|
145 | QTest::newRow("3 series, 2 new axis") << 3 << 0 << 2; | |
|
146 | QTest::newRow("3 series, 1 new axis") << 3 << 0 << 1; | |
|
147 | QTest::newRow("3 series, default + 1 new axis") << 3 << 0 << 1; | |
|
146 | 148 | } |
|
147 | 149 | |
|
148 | 150 | void tst_ChartDataSet::addSeries() |
|
149 | 151 | { |
|
150 |
|
|
|
151 |
|
|
|
152 | QFETCH(int, defaultAxisCount); | |
|
153 | QFETCH(int, firstAxisCount); | |
|
154 | QFETCH(int, secoundAxisCount); | |
|
152 | 155 | |
|
153 |
|
|
|
156 | ChartDataSet dataSet; | |
|
154 | 157 | |
|
155 |
|
|
|
156 | QSignalSpy spy1(&dataSet, | |
|
157 | SIGNAL(axisRangeChanged(QChartAxis*, QStringList const&))); | |
|
158 |
|
|
|
159 |
|
|
|
160 | QSignalSpy spy4(&dataSet, | |
|
161 | SIGNAL(seriesDomainChanged(QSeries*, Domain const&))); | |
|
162 | QSignalSpy spy5(&dataSet, SIGNAL(seriesRemoved(QSeries*))); | |
|
158 | QSignalSpy spy0(&dataSet, SIGNAL(axisAdded(QChartAxis*))); | |
|
159 | QSignalSpy spy1(&dataSet, SIGNAL(axisRangeChanged(QChartAxis*, QStringList const&))); | |
|
160 | QSignalSpy spy2(&dataSet, SIGNAL(axisRemoved(QChartAxis*))); | |
|
161 | QSignalSpy spy3(&dataSet, SIGNAL(seriesAdded(QSeries*))); | |
|
162 | QSignalSpy spy4(&dataSet, SIGNAL(seriesDomainChanged(QSeries*, Domain const&))); | |
|
163 | QSignalSpy spy5(&dataSet, SIGNAL(seriesRemoved(QSeries*))); | |
|
163 | 164 | |
|
164 | QList<QChartAxis*> axisList; | |
|
165 | for (int i = 0; i < defaultAxisCount; i++) { | |
|
166 | QLineSeries* series = new QLineSeries(); | |
|
167 | dataSet.addSeries(series); | |
|
168 | } | |
|
165 | 169 | |
|
166 | for (int i = 0; i < axisYCount; i++) { | |
|
167 | QChartAxis* axis = new QChartAxis(); | |
|
168 | axisList << axis; | |
|
169 | } | |
|
170 | QChartAxis* firstAxis = new QChartAxis(); | |
|
170 | 171 | |
|
171 | QList<QChartAxis*>::iterator iterator = axisList.begin(); | |
|
172 | for (int i = 0; i < firstAxisCount; i++) { | |
|
173 | QLineSeries* series = new QLineSeries(); | |
|
174 | dataSet.addSeries(series, firstAxis); | |
|
175 | } | |
|
172 | 176 | |
|
173 | for (int i = 0; i < seriesCount; i++) { | |
|
174 | QChartAxis* axisY = 0; | |
|
175 | QLineSeries* series = new QLineSeries(); | |
|
176 | if (iterator != axisList.end()) { | |
|
177 | axisY = *iterator; | |
|
178 | iterator++; | |
|
179 | } else if (axisList.count() > 0) { | |
|
180 | iterator--; | |
|
181 | axisY = *iterator; | |
|
182 | iterator++; | |
|
183 | } | |
|
184 | dataSet.addSeries(series, axisY); | |
|
185 | } | |
|
177 | QChartAxis* secoundAxis = new QChartAxis(); | |
|
178 | ||
|
179 | for (int i = 0; i < secoundAxisCount; i++) { | |
|
180 | QLineSeries* series = new QLineSeries(); | |
|
181 | dataSet.addSeries(series, secoundAxis); | |
|
182 | } | |
|
186 | 183 | |
|
187 | //default axis | |
|
188 | if (axisYCount == 0) | |
|
189 | axisYCount+=2; | |
|
190 | else | |
|
191 | axisYCount++; | |
|
184 | int axisCount = 1; | |
|
192 | 185 | |
|
193 | QCOMPARE(spy0.count(), axisYCount); | |
|
194 | QCOMPARE(spy1.count(), seriesCount*2); | |
|
195 | QCOMPARE(spy2.count(), 0); | |
|
196 | QCOMPARE(spy3.count(), seriesCount); | |
|
197 | QCOMPARE(spy4.count(), seriesCount); | |
|
198 | QCOMPARE(spy5.count(), 0); | |
|
186 | if (defaultAxisCount > 0) | |
|
187 | axisCount++; | |
|
188 | if (firstAxisCount > 0) | |
|
189 | axisCount++; | |
|
190 | if (secoundAxisCount > 0) | |
|
191 | axisCount++; | |
|
199 | 192 | |
|
200 | QCOMPARE(dataSet.domainIndex(), 0); | |
|
193 | QCOMPARE(spy0.count(), axisCount); | |
|
194 | QCOMPARE(spy1.count(), (defaultAxisCount + firstAxisCount + secoundAxisCount)*2); | |
|
195 | QCOMPARE(spy2.count(), 0); | |
|
196 | QCOMPARE(spy3.count(), defaultAxisCount + firstAxisCount + secoundAxisCount); | |
|
197 | ||
|
198 | int i = 0; | |
|
199 | while (defaultAxisCount) { | |
|
200 | i+=defaultAxisCount; | |
|
201 | defaultAxisCount--; | |
|
202 | } | |
|
203 | int j = 0; | |
|
204 | while (firstAxisCount>0) { | |
|
205 | j += firstAxisCount; | |
|
206 | firstAxisCount--; | |
|
207 | } | |
|
208 | int k = 0; | |
|
209 | while (secoundAxisCount>0) { | |
|
210 | k += secoundAxisCount; | |
|
211 | secoundAxisCount--; | |
|
212 | } | |
|
213 | QCOMPARE(spy4.count(),i + j + k); | |
|
214 | QCOMPARE(spy5.count(), 0); | |
|
215 | ||
|
216 | QCOMPARE(dataSet.domainIndex(), 0); | |
|
201 | 217 | } |
|
202 | 218 | |
|
203 | 219 | void tst_ChartDataSet::axisY_data() |
@@ -344,7 +360,7 void tst_ChartDataSet::domain() | |||
|
344 | 360 | QCOMPARE(spy1.count(), 6); |
|
345 | 361 | QCOMPARE(spy2.count(), 0); |
|
346 | 362 | QCOMPARE(spy3.count(), 3); |
|
347 |
QCOMPARE(spy4.count(), |
|
|
363 | QCOMPARE(spy4.count(), 6); | |
|
348 | 364 | QCOMPARE(spy5.count(), 0); |
|
349 | 365 | } |
|
350 | 366 |
General Comments 0
You need to be logged in to leave comments.
Login now