##// END OF EJS Templates
Fix issues based on android testing...
Miikka Heikkinen -
r2826:78282651dc64
parent child
Show More
@@ -1,118 +1,119
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2015 The Qt Company Ltd
4 4 ** All rights reserved.
5 5 ** For any questions to The Qt Company, please use contact form at http://qt.io
6 6 **
7 7 ** This file is part of the Qt Charts module.
8 8 **
9 9 ** Licensees holding valid commercial license for Qt may use this file in
10 10 ** accordance with the Qt License Agreement provided with the Software
11 11 ** or, alternatively, in accordance with the terms contained in a written
12 12 ** agreement between you and The Qt Company.
13 13 **
14 14 ** If you have questions regarding the use of this file, please use
15 15 ** contact form at http://qt.io
16 16 **
17 17 ****************************************************************************/
18 18
19 19 #include "datasource.h"
20 20 #include <QtCore/QtMath>
21 21
22 22 QT_CHARTS_USE_NAMESPACE
23 23
24 24 DataSource::DataSource(QObject *parent) :
25 25 QObject(parent),
26 26 m_index(-1)
27 27 {
28 28 generateData(0, 0, 0);
29 29 }
30 30
31 31 void DataSource::update(QAbstractSeries *series, int seriesIndex)
32 32 {
33 33 if (series) {
34 34 QXYSeries *xySeries = static_cast<QXYSeries *>(series);
35 35 const QVector<QVector<QPointF> > &seriesData = m_data.at(seriesIndex);
36 36 if (seriesIndex == 0)
37 37 m_index++;
38 38 if (m_index > seriesData.count() - 1)
39 39 m_index = 0;
40 40
41 41 QVector<QPointF> points = seriesData.at(m_index);
42 42 // Use replace instead of clear + append, it's optimized for performance
43 43 xySeries->replace(points);
44 44 }
45 45 }
46 46
47 47 void DataSource::handleSceneChanged()
48 48 {
49 49 m_dataUpdater.start();
50 50 }
51 51
52 52 void DataSource::updateAllSeries()
53 53 {
54 54 static int frameCount = 0;
55 55 static QString labelText = QStringLiteral("FPS: %1");
56 56
57 57 for (int i = 0; i < m_seriesList.size(); i++)
58 58 update(m_seriesList[i], i);
59 59
60 60 frameCount++;
61 61 int elapsed = m_fpsTimer.elapsed();
62 62 if (elapsed >= 1000) {
63 63 elapsed = m_fpsTimer.restart();
64 64 qreal fps = qreal(0.1 * int(10000.0 * (qreal(frameCount) / qreal(elapsed))));
65 65 m_fpsLabel->setText(labelText.arg(QString::number(fps, 'f', 1)));
66 m_fpsLabel->adjustSize();
66 67 frameCount = 0;
67 68 }
68 69 }
69 70
70 71 void DataSource::startUpdates(const QList<QXYSeries *> &seriesList, QLabel *fpsLabel)
71 72 {
72 73 m_seriesList = seriesList;
73 74 m_fpsLabel = fpsLabel;
74 75
75 76 m_dataUpdater.setInterval(0);
76 77 m_dataUpdater.setSingleShot(true);
77 78 QObject::connect(&m_dataUpdater, &QTimer::timeout,
78 79 this, &DataSource::updateAllSeries);
79 80
80 81 m_fpsTimer.start();
81 82 updateAllSeries();
82 83 }
83 84
84 85 void DataSource::generateData(int seriesCount, int rowCount, int colCount)
85 86 {
86 87 // Remove previous data
87 88 foreach (QVector<QVector<QPointF> > seriesData, m_data) {
88 89 foreach (QVector<QPointF> row, seriesData)
89 90 row.clear();
90 91 }
91 92
92 93 m_data.clear();
93 94
94 95 qreal xAdjustment = 20.0 / (colCount * rowCount);
95 96 qreal yMultiplier = 3.0 / qreal(seriesCount);
96 97
97 98 // Append the new data depending on the type
98 99 for (int k(0); k < seriesCount; k++) {
99 100 QVector<QVector<QPointF> > seriesData;
100 101 qreal height = qreal(k) * (10.0 / qreal(seriesCount)) + 0.3;
101 102 for (int i(0); i < rowCount; i++) {
102 103 QVector<QPointF> points;
103 104 points.reserve(colCount);
104 105 for (int j(0); j < colCount; j++) {
105 106 qreal x(0);
106 107 qreal y(0);
107 108 // data with sin + random component
108 109 y = height + (yMultiplier * qSin(3.14159265358979 / 50 * j)
109 110 + (yMultiplier * (qreal) rand() / (qreal) RAND_MAX));
110 111 // 0.000001 added to make values logaxis compatible
111 112 x = 0.000001 + 20.0 * (qreal(j) / qreal(colCount)) + (xAdjustment * qreal(i));
112 113 points.append(QPointF(x, y));
113 114 }
114 115 seriesData.append(points);
115 116 }
116 117 m_data.append(seriesData);
117 118 }
118 119 }
@@ -1,167 +1,168
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2015 The Qt Company Ltd
4 4 ** All rights reserved.
5 5 ** For any questions to The Qt Company, please use contact form at http://qt.io
6 6 **
7 7 ** This file is part of the Qt Charts module.
8 8 **
9 9 ** Licensees holding valid commercial license for Qt may use this file in
10 10 ** accordance with the Qt License Agreement provided with the Software
11 11 ** or, alternatively, in accordance with the terms contained in a written
12 12 ** agreement between you and The Qt Company.
13 13 **
14 14 ** If you have questions regarding the use of this file, please use
15 15 ** contact form at http://qt.io
16 16 **
17 17 ****************************************************************************/
18 18
19 19 #include "datasource.h"
20 20 #include <QtWidgets/QApplication>
21 21 #include <QtWidgets/QMainWindow>
22 22 #include <QtCharts/QChartView>
23 23 #include <QtCharts/QLineSeries>
24 24 #include <QtCharts/QScatterSeries>
25 25 #include <QtCharts/QValueAxis>
26 26 #include <QtCharts/QLogValueAxis>
27 27 #include <QtWidgets/QLabel>
28 28
29 29 // Uncomment to use logarithmic axes instead of regular value axes
30 30 //#define USE_LOG_AXIS
31 31
32 32 // Uncomment to use regular series instead of OpenGL accelerated series
33 33 //#define DONT_USE_GL_SERIES
34 34
35 35 // Uncomment to add a simple regular series (thick line) and a matching OpenGL series (thinner line)
36 36 // to verify the series have same visible geometry.
37 37 //#define ADD_SIMPLE_SERIES
38 38
39 39 QT_CHARTS_USE_NAMESPACE
40 40
41 41 int main(int argc, char *argv[])
42 42 {
43 43 QApplication a(argc, argv);
44 44 QStringList colors;
45 45 colors << "red" << "blue" << "green" << "black";
46 46
47 47 QChart *chart = new QChart();
48 48 chart->legend()->hide();
49 49
50 50 #ifdef USE_LOG_AXIS
51 51 QLogValueAxis *axisX = new QLogValueAxis;
52 52 QLogValueAxis *axisY = new QLogValueAxis;
53 53 #else
54 54 QValueAxis *axisX = new QValueAxis;
55 55 QValueAxis *axisY = new QValueAxis;
56 56 #endif
57 57
58 58 chart->addAxis(axisX, Qt::AlignBottom);
59 59 chart->addAxis(axisY, Qt::AlignLeft);
60 60
61 61 const int seriesCount = 10;
62 62 #ifdef DONT_USE_GL_SERIES
63 63 const int pointCount = 100;
64 64 chart->setTitle("Unaccelerated Series");
65 65 #else
66 66 const int pointCount = 10000;
67 67 chart->setTitle("OpenGL Accelerated Series");
68 68 #endif
69 69
70 70 QList<QXYSeries *> seriesList;
71 71 for (int i = 0; i < seriesCount; i++) {
72 72 QXYSeries *series = 0;
73 73 int colorIndex = i % colors.size();
74 74 if (i % 2) {
75 75 series = new QScatterSeries;
76 76 QScatterSeries *scatter = static_cast<QScatterSeries *>(series);
77 77 scatter->setColor(QColor(colors.at(colorIndex)));
78 78 scatter->setMarkerSize(qreal(colorIndex + 2) / 2.0);
79 79 // Scatter pen doesn't have affect in OpenGL drawing, but if you disable OpenGL drawing
80 80 // this makes the marker border visible and gives comparable marker size to OpenGL
81 81 // scatter points.
82 82 scatter->setPen(QPen("black"));
83 83 } else {
84 84 series = new QLineSeries;
85 85 series->setPen(QPen(QBrush(QColor(colors.at(colorIndex))),
86 86 qreal(colorIndex + 2) / 2.0));
87 87 }
88 88 seriesList.append(series);
89 89 #ifdef DONT_USE_GL_SERIES
90 90 series->setUseOpenGL(false);
91 91 #else
92 92 //![1]
93 93 series->setUseOpenGL(true);
94 94 //![1]
95 95 #endif
96 96 chart->addSeries(series);
97 97 series->attachAxis(axisX);
98 98 series->attachAxis(axisY);
99 99 }
100 100
101 101 if (axisX->type() == QAbstractAxis::AxisTypeLogValue)
102 102 axisX->setRange(0.1, 20.0);
103 103 else
104 104 axisX->setRange(0, 20.0);
105 105
106 106 if (axisY->type() == QAbstractAxis::AxisTypeLogValue)
107 107 axisY->setRange(0.1, 10.0);
108 108 else
109 109 axisY->setRange(0, 10.0);
110 110
111 111 #ifdef ADD_SIMPLE_SERIES
112 112 QLineSeries *simpleRasterSeries = new QLineSeries;
113 113 *simpleRasterSeries << QPointF(0.001, 0.001)
114 114 << QPointF(2.5, 8.0)
115 115 << QPointF(5.0, 4.0)
116 116 << QPointF(7.5, 9.0)
117 117 << QPointF(10.0, 0.001)
118 118 << QPointF(12.5, 2.0)
119 119 << QPointF(15.0, 1.0)
120 120 << QPointF(17.5, 6.0)
121 121 << QPointF(20.0, 10.0);
122 122 simpleRasterSeries->setUseOpenGL(false);
123 123 simpleRasterSeries->setPen(QPen(QBrush("magenta"), 8));
124 124 chart->addSeries(simpleRasterSeries);
125 125 simpleRasterSeries->attachAxis(axisX);
126 126 simpleRasterSeries->attachAxis(axisY);
127 127
128 128 QLineSeries *simpleGLSeries = new QLineSeries;
129 129 simpleGLSeries->setUseOpenGL(true);
130 130 simpleGLSeries->setPen(QPen(QBrush("black"), 2));
131 131 simpleGLSeries->replace(simpleRasterSeries->points());
132 132 chart->addSeries(simpleGLSeries);
133 133 simpleGLSeries->attachAxis(axisX);
134 134 simpleGLSeries->attachAxis(axisY);
135 135 #endif
136 136
137 137 QChartView *chartView = new QChartView(chart);
138 138
139 139 QMainWindow window;
140 140 window.setCentralWidget(chartView);
141 141 window.resize(600, 400);
142 142 window.show();
143 143
144 144 DataSource dataSource;
145 145 dataSource.generateData(seriesCount, 10, pointCount);
146 146
147 147 QLabel *fpsLabel = new QLabel(&window);
148 148 QLabel *countLabel = new QLabel(&window);
149 149 QString countText = QStringLiteral("Total point count: %1");
150 150 countLabel->setText(countText.arg(pointCount * seriesCount));
151 countLabel->resize(window.width(), countLabel->height());
152 fpsLabel->move(10,2);
151 countLabel->adjustSize();
152 fpsLabel->move(10, 2);
153 fpsLabel->adjustSize();
153 154 fpsLabel->raise();
154 155 fpsLabel->show();
155 countLabel->move(10, 14);
156 countLabel->move(10, fpsLabel->height());
156 157 fpsLabel->raise();
157 158 countLabel->show();
158 159
159 160 // We can get more than one changed event per frame, so do async update.
160 161 // This also allows the application to be responsive.
161 162 QObject::connect(chart->scene(), &QGraphicsScene::changed,
162 163 &dataSource, &DataSource::handleSceneChanged);
163 164
164 165 dataSource.startUpdates(seriesList, fpsLabel);
165 166
166 167 return a.exec();
167 168 }
@@ -1,96 +1,96
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2015 The Qt Company Ltd
4 4 ** All rights reserved.
5 5 ** For any questions to The Qt Company, please use contact form at http://qt.io
6 6 **
7 7 ** This file is part of the Qt Charts module.
8 8 **
9 9 ** Licensees holding valid commercial license for Qt may use this file in
10 10 ** accordance with the Qt License Agreement provided with the Software
11 11 ** or, alternatively, in accordance with the terms contained in a written
12 12 ** agreement between you and The Qt Company.
13 13 **
14 14 ** If you have questions regarding the use of this file, please use
15 15 ** contact form at http://qt.io
16 16 **
17 17 ****************************************************************************/
18 18
19 19 import QtQuick 2.1
20 20 import QtQuick.Layouts 1.0
21 21
22 22 ColumnLayout {
23 23 property alias openGLButton: openGLButton
24 24 spacing: 8
25 25 Layout.fillHeight: true
26 26 signal animationsEnabled(bool enabled)
27 27 signal seriesTypeChanged(string type)
28 28 signal refreshRateChanged(variant rate);
29 29 signal signalSourceChanged(string source, int signalCount, int sampleCount);
30 30 signal antialiasingEnabled(bool enabled)
31 31 signal openGlChanged(bool enabled)
32 32
33 33 Text {
34 34 text: "Scope"
35 35 font.pointSize: 18
36 36 color: "white"
37 37 }
38 38
39 39 MultiButton {
40 40 id: openGLButton
41 41 text: "OpenGL: "
42 42 items: ["false", "true"]
43 43 currentSelection: 0
44 44 onSelectionChanged: openGlChanged(currentSelection == 1);
45 45 }
46 46
47 47 MultiButton {
48 48 text: "Graph: "
49 49 items: ["line", "spline", "scatter"]
50 50 currentSelection: 0
51 51 onSelectionChanged: seriesTypeChanged(items[currentSelection]);
52 52 }
53 53
54 54 MultiButton {
55 55 id: signalSourceButton
56 56 text: "Source: "
57 57 items: ["sin", "linear"]
58 58 currentSelection: 0
59 59 onSelectionChanged: signalSourceChanged(
60 60 selection,
61 61 5,
62 62 sampleCountButton.items[sampleCountButton.currentSelection]);
63 63 }
64 64
65 65 MultiButton {
66 66 id: sampleCountButton
67 67 text: "Samples: "
68 items: [6, 128, 1024, 10000]
68 items: ["6", "128", "1024", "10000"]
69 69 currentSelection: 2
70 70 onSelectionChanged: signalSourceChanged(
71 71 signalSourceButton.items[signalSourceButton.currentSelection],
72 72 5,
73 73 selection);
74 74 }
75 75
76 76 MultiButton {
77 77 text: "Refresh rate: "
78 items: [1, 24, 60, 100]
78 items: ["1", "24", "60"]
79 79 currentSelection: 2
80 80 onSelectionChanged: refreshRateChanged(items[currentSelection]);
81 81 }
82 82
83 83 MultiButton {
84 84 text: "Animations: "
85 85 items: ["OFF", "ON"]
86 86 currentSelection: 0
87 87 onSelectionChanged: animationsEnabled(currentSelection == 1);
88 88 }
89 89
90 90 MultiButton {
91 91 text: "Antialias: "
92 92 items: ["OFF", "ON"]
93 93 currentSelection: 0
94 94 onSelectionChanged: antialiasingEnabled(currentSelection == 1);
95 95 }
96 96 }
@@ -1,58 +1,59
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2015 The Qt Company Ltd
4 4 ** All rights reserved.
5 5 ** For any questions to The Qt Company, please use contact form at http://qt.io
6 6 **
7 7 ** This file is part of the Qt Charts module.
8 8 **
9 9 ** Licensees holding valid commercial license for Qt may use this file in
10 10 ** accordance with the Qt License Agreement provided with the Software
11 11 ** or, alternatively, in accordance with the terms contained in a written
12 12 ** agreement between you and The Qt Company.
13 13 **
14 14 ** If you have questions regarding the use of this file, please use
15 15 ** contact form at http://qt.io
16 16 **
17 17 ****************************************************************************/
18 18
19 19 #include <private/chartitem_p.h>
20 20 #include <private/qabstractseries_p.h>
21 21 #include <private/abstractdomain_p.h>
22 #include <QtGui/QPainter>
22 23
23 24 QT_CHARTS_BEGIN_NAMESPACE
24 25
25 26 ChartItem::ChartItem(QAbstractSeriesPrivate *series,QGraphicsItem* item):
26 27 ChartElement(item),
27 28 m_validData(true),
28 29 m_series(series)
29 30 {
30 31
31 32 }
32 33
33 34 AbstractDomain* ChartItem::domain() const
34 35 {
35 36 return m_series->domain();
36 37 }
37 38
38 39 void ChartItem::handleDomainUpdated()
39 40 {
40 41 qWarning() << __FUNCTION__<< "Slot not implemented";
41 42 }
42 43
43 44 void ChartItem::reversePainter(QPainter *painter, const QRectF &clipRect)
44 45 {
45 46 if (m_series->reverseXAxis()) {
46 47 painter->translate(clipRect.width(), 0);
47 48 painter->scale(-1, 1);
48 49 }
49 50
50 51 if (m_series->reverseYAxis()) {
51 52 painter->translate(0, clipRect.height());
52 53 painter->scale(1, -1);
53 54 }
54 55 }
55 56
56 57 #include "moc_chartitem_p.cpp"
57 58
58 59 QT_CHARTS_END_NAMESPACE
@@ -1,569 +1,570
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2015 The Qt Company Ltd
4 4 ** All rights reserved.
5 5 ** For any questions to The Qt Company, please use contact form at http://qt.io
6 6 **
7 7 ** This file is part of the Qt Charts module.
8 8 **
9 9 ** Licensees holding valid commercial license for Qt may use this file in
10 10 ** accordance with the Qt License Agreement provided with the Software
11 11 ** or, alternatively, in accordance with the terms contained in a written
12 12 ** agreement between you and The Qt Company.
13 13 **
14 14 ** If you have questions regarding the use of this file, please use
15 15 ** contact form at http://qt.io
16 16 **
17 17 ****************************************************************************/
18 18 #include <private/chartpresenter_p.h>
19 19 #include <QtCharts/QChart>
20 20 #include <private/chartitem_p.h>
21 21 #include <private/qchart_p.h>
22 22 #include <QtCharts/QAbstractAxis>
23 23 #include <private/qabstractaxis_p.h>
24 24 #include <private/chartdataset_p.h>
25 25 #include <private/chartanimation_p.h>
26 26 #include <private/qabstractseries_p.h>
27 27 #include <QtCharts/QAreaSeries>
28 28 #include <private/chartaxiselement_p.h>
29 29 #include <private/chartbackground_p.h>
30 30 #include <private/cartesianchartlayout_p.h>
31 31 #include <private/polarchartlayout_p.h>
32 32 #include <private/charttitle_p.h>
33 33 #include <QtCore/QTimer>
34 34 #include <QtGui/QTextDocument>
35 #include <QtWidgets/QGraphicsScene>
35 36
36 37 QT_CHARTS_BEGIN_NAMESPACE
37 38
38 39 ChartPresenter::ChartPresenter(QChart *chart, QChart::ChartType type)
39 40 : QObject(chart),
40 41 m_chart(chart),
41 42 m_options(QChart::NoAnimation),
42 43 m_animationDuration(ChartAnimationDuration),
43 44 m_animationCurve(QEasingCurve::OutQuart),
44 45 m_state(ShowState),
45 46 m_background(0),
46 47 m_plotAreaBackground(0),
47 48 m_title(0),
48 49 m_localizeNumbers(false)
49 50 #ifndef QT_NO_OPENGL
50 51 , m_glWidget(0)
51 52 , m_glUseWidget(true)
52 53 #endif
53 54 {
54 55 if (type == QChart::ChartTypeCartesian)
55 56 m_layout = new CartesianChartLayout(this);
56 57 else if (type == QChart::ChartTypePolar)
57 58 m_layout = new PolarChartLayout(this);
58 59 Q_ASSERT(m_layout);
59 60 }
60 61
61 62 ChartPresenter::~ChartPresenter()
62 63 {
63 64 #ifndef QT_NO_OPENGL
64 65 delete m_glWidget.data();
65 66 #endif
66 67 }
67 68
68 69 void ChartPresenter::setGeometry(const QRectF rect)
69 70 {
70 71 if (m_rect != rect) {
71 72 m_rect = rect;
72 73 foreach (ChartItem *chart, m_chartItems) {
73 74 chart->domain()->setSize(rect.size());
74 75 chart->setPos(rect.topLeft());
75 76 }
76 77 #ifndef QT_NO_OPENGL
77 78 if (!m_glWidget.isNull())
78 79 m_glWidget->setGeometry(m_rect.toRect());
79 80 #endif
80 81 emit plotAreaChanged(m_rect);
81 82 }
82 83 }
83 84
84 85 QRectF ChartPresenter::geometry() const
85 86 {
86 87 return m_rect;
87 88 }
88 89
89 90 void ChartPresenter::handleAxisAdded(QAbstractAxis *axis)
90 91 {
91 92 axis->d_ptr->initializeGraphics(rootItem());
92 93 axis->d_ptr->initializeAnimations(m_options, m_animationDuration, m_animationCurve);
93 94 ChartAxisElement *item = axis->d_ptr->axisItem();
94 95 item->setPresenter(this);
95 96 item->setThemeManager(m_chart->d_ptr->m_themeManager);
96 97 m_axisItems<<item;
97 98 m_axes<<axis;
98 99 m_layout->invalidate();
99 100 }
100 101
101 102 void ChartPresenter::handleAxisRemoved(QAbstractAxis *axis)
102 103 {
103 104 ChartAxisElement *item = axis->d_ptr->m_item.take();
104 105 item->hide();
105 106 item->disconnect();
106 107 item->deleteLater();
107 108 m_axisItems.removeAll(item);
108 109 m_axes.removeAll(axis);
109 110 m_layout->invalidate();
110 111 }
111 112
112 113
113 114 void ChartPresenter::handleSeriesAdded(QAbstractSeries *series)
114 115 {
115 116 series->d_ptr->initializeGraphics(rootItem());
116 117 series->d_ptr->initializeAnimations(m_options, m_animationDuration, m_animationCurve);
117 118 series->d_ptr->setPresenter(this);
118 119 ChartItem *chart = series->d_ptr->chartItem();
119 120 chart->setPresenter(this);
120 121 chart->setThemeManager(m_chart->d_ptr->m_themeManager);
121 122 chart->setDataSet(m_chart->d_ptr->m_dataset);
122 123 chart->domain()->setSize(m_rect.size());
123 124 chart->setPos(m_rect.topLeft());
124 125 chart->handleDomainUpdated(); //this could be moved to intializeGraphics when animator is refactored
125 126 m_chartItems<<chart;
126 127 m_series<<series;
127 128 m_layout->invalidate();
128 129 }
129 130
130 131 void ChartPresenter::handleSeriesRemoved(QAbstractSeries *series)
131 132 {
132 133 ChartItem *chart = series->d_ptr->m_item.take();
133 134 chart->hide();
134 135 chart->disconnect();
135 136 chart->deleteLater();
136 137 if (chart->animation())
137 138 chart->animation()->stopAndDestroyLater();
138 139 m_chartItems.removeAll(chart);
139 140 m_series.removeAll(series);
140 141 m_layout->invalidate();
141 142 }
142 143
143 144 void ChartPresenter::setAnimationOptions(QChart::AnimationOptions options)
144 145 {
145 146 if (m_options != options) {
146 147 QChart::AnimationOptions oldOptions = m_options;
147 148 m_options = options;
148 149 if (options.testFlag(QChart::SeriesAnimations) != oldOptions.testFlag(QChart::SeriesAnimations)) {
149 150 foreach (QAbstractSeries *series, m_series)
150 151 series->d_ptr->initializeAnimations(m_options, m_animationDuration,
151 152 m_animationCurve);
152 153 }
153 154 if (options.testFlag(QChart::GridAxisAnimations) != oldOptions.testFlag(QChart::GridAxisAnimations)) {
154 155 foreach (QAbstractAxis *axis, m_axes)
155 156 axis->d_ptr->initializeAnimations(m_options, m_animationDuration, m_animationCurve);
156 157 }
157 158 m_layout->invalidate(); // So that existing animations don't just stop halfway
158 159 }
159 160 }
160 161
161 162 void ChartPresenter::setAnimationDuration(int msecs)
162 163 {
163 164 if (m_animationDuration != msecs) {
164 165 m_animationDuration = msecs;
165 166 foreach (QAbstractSeries *series, m_series)
166 167 series->d_ptr->initializeAnimations(m_options, m_animationDuration, m_animationCurve);
167 168 foreach (QAbstractAxis *axis, m_axes)
168 169 axis->d_ptr->initializeAnimations(m_options, m_animationDuration, m_animationCurve);
169 170 m_layout->invalidate(); // So that existing animations don't just stop halfway
170 171 }
171 172 }
172 173
173 174 void ChartPresenter::setAnimationEasingCurve(const QEasingCurve &curve)
174 175 {
175 176 if (m_animationCurve != curve) {
176 177 m_animationCurve = curve;
177 178 foreach (QAbstractSeries *series, m_series)
178 179 series->d_ptr->initializeAnimations(m_options, m_animationDuration, m_animationCurve);
179 180 foreach (QAbstractAxis *axis, m_axes)
180 181 axis->d_ptr->initializeAnimations(m_options, m_animationDuration, m_animationCurve);
181 182 m_layout->invalidate(); // So that existing animations don't just stop halfway
182 183 }
183 184 }
184 185
185 186 void ChartPresenter::setState(State state,QPointF point)
186 187 {
187 188 m_state=state;
188 189 m_statePoint=point;
189 190 }
190 191
191 192 QChart::AnimationOptions ChartPresenter::animationOptions() const
192 193 {
193 194 return m_options;
194 195 }
195 196
196 197 void ChartPresenter::createBackgroundItem()
197 198 {
198 199 if (!m_background) {
199 200 m_background = new ChartBackground(rootItem());
200 201 m_background->setPen(Qt::NoPen); // Theme doesn't touch pen so don't use default
201 202 m_background->setBrush(QChartPrivate::defaultBrush());
202 203 m_background->setZValue(ChartPresenter::BackgroundZValue);
203 204 }
204 205 }
205 206
206 207 void ChartPresenter::createPlotAreaBackgroundItem()
207 208 {
208 209 if (!m_plotAreaBackground) {
209 210 if (m_chart->chartType() == QChart::ChartTypeCartesian)
210 211 m_plotAreaBackground = new QGraphicsRectItem(rootItem());
211 212 else
212 213 m_plotAreaBackground = new QGraphicsEllipseItem(rootItem());
213 214 // Use transparent pen instead of Qt::NoPen, as Qt::NoPen causes
214 215 // antialising artifacts with axis lines for some reason.
215 216 m_plotAreaBackground->setPen(QPen(Qt::transparent));
216 217 m_plotAreaBackground->setBrush(Qt::NoBrush);
217 218 m_plotAreaBackground->setZValue(ChartPresenter::PlotAreaZValue);
218 219 m_plotAreaBackground->setVisible(false);
219 220 }
220 221 }
221 222
222 223 void ChartPresenter::createTitleItem()
223 224 {
224 225 if (!m_title) {
225 226 m_title = new ChartTitle(rootItem());
226 227 m_title->setZValue(ChartPresenter::BackgroundZValue);
227 228 }
228 229 }
229 230
230 231 void ChartPresenter::startAnimation(ChartAnimation *animation)
231 232 {
232 233 animation->stop();
233 234 QTimer::singleShot(0, animation, SLOT(startChartAnimation()));
234 235 }
235 236
236 237 void ChartPresenter::setBackgroundBrush(const QBrush &brush)
237 238 {
238 239 createBackgroundItem();
239 240 m_background->setBrush(brush);
240 241 m_layout->invalidate();
241 242 }
242 243
243 244 QBrush ChartPresenter::backgroundBrush() const
244 245 {
245 246 if (!m_background)
246 247 return QBrush();
247 248 return m_background->brush();
248 249 }
249 250
250 251 void ChartPresenter::setBackgroundPen(const QPen &pen)
251 252 {
252 253 createBackgroundItem();
253 254 m_background->setPen(pen);
254 255 m_layout->invalidate();
255 256 }
256 257
257 258 QPen ChartPresenter::backgroundPen() const
258 259 {
259 260 if (!m_background)
260 261 return QPen();
261 262 return m_background->pen();
262 263 }
263 264
264 265 void ChartPresenter::setBackgroundRoundness(qreal diameter)
265 266 {
266 267 createBackgroundItem();
267 268 m_background->setDiameter(diameter);
268 269 m_layout->invalidate();
269 270 }
270 271
271 272 qreal ChartPresenter::backgroundRoundness() const
272 273 {
273 274 if (!m_background)
274 275 return 0;
275 276 return m_background->diameter();
276 277 }
277 278
278 279 void ChartPresenter::setPlotAreaBackgroundBrush(const QBrush &brush)
279 280 {
280 281 createPlotAreaBackgroundItem();
281 282 m_plotAreaBackground->setBrush(brush);
282 283 m_layout->invalidate();
283 284 }
284 285
285 286 QBrush ChartPresenter::plotAreaBackgroundBrush() const
286 287 {
287 288 if (!m_plotAreaBackground)
288 289 return QBrush();
289 290 return m_plotAreaBackground->brush();
290 291 }
291 292
292 293 void ChartPresenter::setPlotAreaBackgroundPen(const QPen &pen)
293 294 {
294 295 createPlotAreaBackgroundItem();
295 296 m_plotAreaBackground->setPen(pen);
296 297 m_layout->invalidate();
297 298 }
298 299
299 300 QPen ChartPresenter::plotAreaBackgroundPen() const
300 301 {
301 302 if (!m_plotAreaBackground)
302 303 return QPen();
303 304 return m_plotAreaBackground->pen();
304 305 }
305 306
306 307 void ChartPresenter::setTitle(const QString &title)
307 308 {
308 309 createTitleItem();
309 310 m_title->setText(title);
310 311 m_layout->invalidate();
311 312 }
312 313
313 314 QString ChartPresenter::title() const
314 315 {
315 316 if (!m_title)
316 317 return QString();
317 318 return m_title->text();
318 319 }
319 320
320 321 void ChartPresenter::setTitleFont(const QFont &font)
321 322 {
322 323 createTitleItem();
323 324 m_title->setFont(font);
324 325 m_layout->invalidate();
325 326 }
326 327
327 328 QFont ChartPresenter::titleFont() const
328 329 {
329 330 if (!m_title)
330 331 return QFont();
331 332 return m_title->font();
332 333 }
333 334
334 335 void ChartPresenter::setTitleBrush(const QBrush &brush)
335 336 {
336 337 createTitleItem();
337 338 m_title->setDefaultTextColor(brush.color());
338 339 m_layout->invalidate();
339 340 }
340 341
341 342 QBrush ChartPresenter::titleBrush() const
342 343 {
343 344 if (!m_title)
344 345 return QBrush();
345 346 return QBrush(m_title->defaultTextColor());
346 347 }
347 348
348 349 void ChartPresenter::setBackgroundVisible(bool visible)
349 350 {
350 351 createBackgroundItem();
351 352 m_background->setVisible(visible);
352 353 }
353 354
354 355
355 356 bool ChartPresenter::isBackgroundVisible() const
356 357 {
357 358 if (!m_background)
358 359 return false;
359 360 return m_background->isVisible();
360 361 }
361 362
362 363 void ChartPresenter::setPlotAreaBackgroundVisible(bool visible)
363 364 {
364 365 createPlotAreaBackgroundItem();
365 366 m_plotAreaBackground->setVisible(visible);
366 367 }
367 368
368 369 bool ChartPresenter::isPlotAreaBackgroundVisible() const
369 370 {
370 371 if (!m_plotAreaBackground)
371 372 return false;
372 373 return m_plotAreaBackground->isVisible();
373 374 }
374 375
375 376 void ChartPresenter::setBackgroundDropShadowEnabled(bool enabled)
376 377 {
377 378 createBackgroundItem();
378 379 m_background->setDropShadowEnabled(enabled);
379 380 }
380 381
381 382 bool ChartPresenter::isBackgroundDropShadowEnabled() const
382 383 {
383 384 if (!m_background)
384 385 return false;
385 386 return m_background->isDropShadowEnabled();
386 387 }
387 388
388 389 void ChartPresenter::setLocalizeNumbers(bool localize)
389 390 {
390 391 m_localizeNumbers = localize;
391 392 m_layout->invalidate();
392 393 }
393 394
394 395 void ChartPresenter::setLocale(const QLocale &locale)
395 396 {
396 397 m_locale = locale;
397 398 m_layout->invalidate();
398 399 }
399 400
400 401 AbstractChartLayout *ChartPresenter::layout()
401 402 {
402 403 return m_layout;
403 404 }
404 405
405 406 QLegend *ChartPresenter::legend()
406 407 {
407 408 return m_chart->legend();
408 409 }
409 410
410 411 void ChartPresenter::setVisible(bool visible)
411 412 {
412 413 m_chart->setVisible(visible);
413 414 }
414 415
415 416 ChartBackground *ChartPresenter::backgroundElement()
416 417 {
417 418 return m_background;
418 419 }
419 420
420 421 QAbstractGraphicsShapeItem *ChartPresenter::plotAreaElement()
421 422 {
422 423 return m_plotAreaBackground;
423 424 }
424 425
425 426 QList<ChartAxisElement *> ChartPresenter::axisItems() const
426 427 {
427 428 return m_axisItems;
428 429 }
429 430
430 431 QList<ChartItem *> ChartPresenter::chartItems() const
431 432 {
432 433 return m_chartItems;
433 434 }
434 435
435 436 ChartTitle *ChartPresenter::titleElement()
436 437 {
437 438 return m_title;
438 439 }
439 440
440 441 QRectF ChartPresenter::textBoundingRect(const QFont &font, const QString &text, qreal angle)
441 442 {
442 443 static QGraphicsTextItem dummyTextItem;
443 444 static bool initMargin = true;
444 445 if (initMargin) {
445 446 dummyTextItem.document()->setDocumentMargin(textMargin());
446 447 initMargin = false;
447 448 }
448 449
449 450 dummyTextItem.setFont(font);
450 451 dummyTextItem.setHtml(text);
451 452 QRectF boundingRect = dummyTextItem.boundingRect();
452 453
453 454 // Take rotation into account
454 455 if (angle) {
455 456 QTransform transform;
456 457 transform.rotate(angle);
457 458 boundingRect = transform.mapRect(boundingRect);
458 459 }
459 460
460 461 return boundingRect;
461 462 }
462 463
463 464 // boundingRect parameter returns the rotated bounding rect of the text
464 465 QString ChartPresenter::truncatedText(const QFont &font, const QString &text, qreal angle,
465 466 qreal maxWidth, qreal maxHeight, QRectF &boundingRect)
466 467 {
467 468 QString truncatedString(text);
468 469 boundingRect = textBoundingRect(font, truncatedString, angle);
469 470 if (boundingRect.width() > maxWidth || boundingRect.height() > maxHeight) {
470 471 // It can be assumed that almost any amount of string manipulation is faster
471 472 // than calculating one bounding rectangle, so first prepare a list of truncated strings
472 473 // to try.
473 474 static QRegExp truncateMatcher(QStringLiteral("&#?[0-9a-zA-Z]*;$"));
474 475
475 476 QVector<QString> testStrings(text.length());
476 477 int count(0);
477 478 static QLatin1Char closeTag('>');
478 479 static QLatin1Char openTag('<');
479 480 static QLatin1Char semiColon(';');
480 481 static QLatin1String ellipsis("...");
481 482 while (truncatedString.length() > 1) {
482 483 int chopIndex(-1);
483 484 int chopCount(1);
484 485 QChar lastChar(truncatedString.at(truncatedString.length() - 1));
485 486
486 487 if (lastChar == closeTag)
487 488 chopIndex = truncatedString.lastIndexOf(openTag);
488 489 else if (lastChar == semiColon)
489 490 chopIndex = truncateMatcher.indexIn(truncatedString, 0);
490 491
491 492 if (chopIndex != -1)
492 493 chopCount = truncatedString.length() - chopIndex;
493 494 truncatedString.chop(chopCount);
494 495 testStrings[count] = truncatedString + ellipsis;
495 496 count++;
496 497 }
497 498
498 499 // Binary search for best fit
499 500 int minIndex(0);
500 501 int maxIndex(count - 1);
501 502 int bestIndex(count);
502 503 QRectF checkRect;
503 504
504 505 while (maxIndex >= minIndex) {
505 506 int mid = (maxIndex + minIndex) / 2;
506 507 checkRect = textBoundingRect(font, testStrings.at(mid), angle);
507 508 if (checkRect.width() > maxWidth || checkRect.height() > maxHeight) {
508 509 // Checked index too large, all under this are also too large
509 510 minIndex = mid + 1;
510 511 } else {
511 512 // Checked index fits, all over this also fit
512 513 maxIndex = mid - 1;
513 514 bestIndex = mid;
514 515 boundingRect = checkRect;
515 516 }
516 517 }
517 518 // Default to "..." if nothing fits
518 519 if (bestIndex == count) {
519 520 boundingRect = textBoundingRect(font, ellipsis, angle);
520 521 truncatedString = ellipsis;
521 522 } else {
522 523 truncatedString = testStrings.at(bestIndex);
523 524 }
524 525 }
525 526
526 527 return truncatedString;
527 528 }
528 529
529 530 QString ChartPresenter::numberToString(double value, char f, int prec)
530 531 {
531 532 if (m_localizeNumbers)
532 533 return m_locale.toString(value, f, prec);
533 534 else
534 535 return QString::number(value, f, prec);
535 536 }
536 537
537 538 QString ChartPresenter::numberToString(int value)
538 539 {
539 540 if (m_localizeNumbers)
540 541 return m_locale.toString(value);
541 542 else
542 543 return QString::number(value);
543 544 }
544 545
545 546 void ChartPresenter::ensureGLWidget()
546 547 {
547 548 #ifndef QT_NO_OPENGL
548 549 // GLWidget pointer is wrapped in QPointer as its parent is not in our control, and therefore
549 550 // can potentially get deleted unexpectedly.
550 551 if (m_glWidget.isNull() && m_glUseWidget && m_chart->scene()) {
551 552 QObject *parent = m_chart->scene()->parent();
552 553 while (parent) {
553 554 QWidget *parentWidget = qobject_cast<QWidget *>(parent);
554 555 if (parentWidget) {
555 556 m_glWidget = new GLWidget(m_chart->d_ptr->m_dataset->glXYSeriesDataManager(),
556 557 parentWidget);
557 558 m_glWidget->setGeometry(m_rect.toRect());
558 559 m_glWidget->show();
559 560 break;
560 561 }
561 562 parent = parent->parent();
562 563 }
563 564 }
564 565 #endif
565 566 }
566 567
567 568 #include "moc_chartpresenter_p.cpp"
568 569
569 570 QT_CHARTS_END_NAMESPACE
@@ -1,208 +1,209
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2015 The Qt Company Ltd
4 4 ** All rights reserved.
5 5 ** For any questions to The Qt Company, please use contact form at http://qt.io
6 6 **
7 7 ** This file is part of the Qt Charts module.
8 8 **
9 9 ** Licensees holding valid commercial license for Qt may use this file in
10 10 ** accordance with the Qt License Agreement provided with the Software
11 11 ** or, alternatively, in accordance with the terms contained in a written
12 12 ** agreement between you and The Qt Company.
13 13 **
14 14 ** If you have questions regarding the use of this file, please use
15 15 ** contact form at http://qt.io
16 16 **
17 17 ****************************************************************************/
18 18
19 19 // W A R N I N G
20 20 // -------------
21 21 //
22 22 // This file is not part of the Qt Chart API. It exists purely as an
23 23 // implementation detail. This header file may change from version to
24 24 // version without notice, or even be removed.
25 25 //
26 26 // We mean it.
27 27
28 28 #ifndef CHARTPRESENTER_H
29 29 #define CHARTPRESENTER_H
30 30
31 31 #include <QtCharts/QChartGlobal>
32 32 #include <QtCharts/QChart> //because of QChart::ChartThemeId
33 33 #include <private/glwidget_p.h>
34 34 #include <QtCore/QRectF>
35 35 #include <QtCore/QMargins>
36 36 #include <QtCore/QLocale>
37 37 #include <QtCore/QPointer>
38 #include <QtCore/QEasingCurve>
38 39
39 40 QT_CHARTS_BEGIN_NAMESPACE
40 41
41 42 class ChartItem;
42 43 class AxisItem;
43 44 class QAbstractSeries;
44 45 class ChartDataSet;
45 46 class AbstractDomain;
46 47 class ChartAxisElement;
47 48 class ChartAnimator;
48 49 class ChartBackground;
49 50 class ChartTitle;
50 51 class ChartAnimation;
51 52 class AbstractChartLayout;
52 53
53 54 class ChartPresenter: public QObject
54 55 {
55 56 Q_OBJECT
56 57 public:
57 58 enum ZValues {
58 59 BackgroundZValue = -1,
59 60 PlotAreaZValue,
60 61 ShadesZValue,
61 62 GridZValue,
62 63 AxisZValue,
63 64 SeriesZValue,
64 65 LineChartZValue = SeriesZValue,
65 66 SplineChartZValue = SeriesZValue,
66 67 BarSeriesZValue = SeriesZValue,
67 68 ScatterSeriesZValue = SeriesZValue,
68 69 PieSeriesZValue = SeriesZValue,
69 70 BoxPlotSeriesZValue = SeriesZValue,
70 71 LegendZValue,
71 72 TopMostZValue
72 73 };
73 74
74 75 enum State {
75 76 ShowState,
76 77 ScrollUpState,
77 78 ScrollDownState,
78 79 ScrollLeftState,
79 80 ScrollRightState,
80 81 ZoomInState,
81 82 ZoomOutState
82 83 };
83 84
84 85 ChartPresenter(QChart *chart, QChart::ChartType type);
85 86 virtual ~ChartPresenter();
86 87
87 88
88 89 void setGeometry(QRectF rect);
89 90 QRectF geometry() const;
90 91
91 92 QGraphicsItem *rootItem(){ return m_chart; }
92 93 ChartBackground *backgroundElement();
93 94 QAbstractGraphicsShapeItem *plotAreaElement();
94 95 ChartTitle *titleElement();
95 96 QList<ChartAxisElement *> axisItems() const;
96 97 QList<ChartItem *> chartItems() const;
97 98
98 99 QLegend *legend();
99 100
100 101 void setBackgroundBrush(const QBrush &brush);
101 102 QBrush backgroundBrush() const;
102 103
103 104 void setBackgroundPen(const QPen &pen);
104 105 QPen backgroundPen() const;
105 106
106 107 void setBackgroundRoundness(qreal diameter);
107 108 qreal backgroundRoundness() const;
108 109
109 110 void setPlotAreaBackgroundBrush(const QBrush &brush);
110 111 QBrush plotAreaBackgroundBrush() const;
111 112
112 113 void setPlotAreaBackgroundPen(const QPen &pen);
113 114 QPen plotAreaBackgroundPen() const;
114 115
115 116 void setTitle(const QString &title);
116 117 QString title() const;
117 118
118 119 void setTitleFont(const QFont &font);
119 120 QFont titleFont() const;
120 121
121 122 void setTitleBrush(const QBrush &brush);
122 123 QBrush titleBrush() const;
123 124
124 125 void setBackgroundVisible(bool visible);
125 126 bool isBackgroundVisible() const;
126 127
127 128 void setPlotAreaBackgroundVisible(bool visible);
128 129 bool isPlotAreaBackgroundVisible() const;
129 130
130 131 void setBackgroundDropShadowEnabled(bool enabled);
131 132 bool isBackgroundDropShadowEnabled() const;
132 133
133 134 void setLocalizeNumbers(bool localize);
134 135 inline bool localizeNumbers() const { return m_localizeNumbers; }
135 136 void setLocale(const QLocale &locale);
136 137 inline const QLocale &locale() const { return m_locale; }
137 138
138 139 void setVisible(bool visible);
139 140
140 141 void setAnimationOptions(QChart::AnimationOptions options);
141 142 QChart::AnimationOptions animationOptions() const;
142 143 void setAnimationDuration(int msecs);
143 144 int animationDuration() const { return m_animationDuration; }
144 145 void setAnimationEasingCurve(const QEasingCurve &curve);
145 146 QEasingCurve animationEasingCurve() const { return m_animationCurve; }
146 147
147 148 void startAnimation(ChartAnimation *animation);
148 149
149 150 void setState(State state,QPointF point);
150 151 State state() const { return m_state; }
151 152 QPointF statePoint() const { return m_statePoint; }
152 153 AbstractChartLayout *layout();
153 154
154 155 QChart::ChartType chartType() const { return m_chart->chartType(); }
155 156 QChart *chart() { return m_chart; }
156 157
157 158 static QRectF textBoundingRect(const QFont &font, const QString &text, qreal angle = 0.0);
158 159 static QString truncatedText(const QFont &font, const QString &text, qreal angle,
159 160 qreal maxWidth, qreal maxHeight, QRectF &boundingRect);
160 161 inline static qreal textMargin() { return qreal(0.5); }
161 162
162 163 QString numberToString(double value, char f = 'g', int prec = 6);
163 164 QString numberToString(int value);
164 165
165 166 void ensureGLWidget();
166 167 void glSetUseWidget(bool enable) { m_glUseWidget = enable; }
167 168
168 169 private:
169 170 void createBackgroundItem();
170 171 void createPlotAreaBackgroundItem();
171 172 void createTitleItem();
172 173
173 174 public Q_SLOTS:
174 175 void handleSeriesAdded(QAbstractSeries *series);
175 176 void handleSeriesRemoved(QAbstractSeries *series);
176 177 void handleAxisAdded(QAbstractAxis *axis);
177 178 void handleAxisRemoved(QAbstractAxis *axis);
178 179
179 180 Q_SIGNALS:
180 181 void plotAreaChanged(const QRectF &plotArea);
181 182
182 183 private:
183 184 QChart *m_chart;
184 185 QList<ChartItem *> m_chartItems;
185 186 QList<ChartAxisElement *> m_axisItems;
186 187 QList<QAbstractSeries *> m_series;
187 188 QList<QAbstractAxis *> m_axes;
188 189 QChart::AnimationOptions m_options;
189 190 int m_animationDuration;
190 191 QEasingCurve m_animationCurve;
191 192 State m_state;
192 193 QPointF m_statePoint;
193 194 AbstractChartLayout *m_layout;
194 195 ChartBackground *m_background;
195 196 QAbstractGraphicsShapeItem *m_plotAreaBackground;
196 197 ChartTitle *m_title;
197 198 QRectF m_rect;
198 199 bool m_localizeNumbers;
199 200 QLocale m_locale;
200 201 #ifndef QT_NO_OPENGL
201 202 QPointer<GLWidget> m_glWidget;
202 203 #endif
203 204 bool m_glUseWidget;
204 205 };
205 206
206 207 QT_CHARTS_END_NAMESPACE
207 208
208 209 #endif /* CHARTPRESENTER_H */
General Comments 0
You need to be logged in to leave comments. Login now