##// END OF EJS Templates
Fix ChartView rotations for non-90 degree steps....
Miikka Heikkinen -
r2507:470a55f27ca3
parent child
Show More
@@ -1,282 +1,285
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2013 Digia Plc
3 ** Copyright (C) 2013 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
6 **
7 ** This file is part of the Qt Commercial Charts Add-on.
7 ** This file is part of the Qt Commercial Charts Add-on.
8 **
8 **
9 ** $QT_BEGIN_LICENSE$
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Commercial licenses may use this file in
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
13 ** a written agreement between you and Digia.
14 **
14 **
15 ** If you have questions regarding the use of this file, please use
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
17 ** $QT_END_LICENSE$
18 **
18 **
19 ****************************************************************************/
19 ****************************************************************************/
20
20
21 #include "qchartview.h"
21 #include "qchartview.h"
22 #include "qchartview_p.h"
22 #include "qchartview_p.h"
23 #include "qchart_p.h"
23 #include "qchart_p.h"
24 #include <QGraphicsScene>
24 #include <QGraphicsScene>
25 #include <QRubberBand>
25 #include <QRubberBand>
26 #include <qmath.h>
27
26
28 /*!
27 /*!
29 \enum QChartView::RubberBand
28 \enum QChartView::RubberBand
30
29
31 This enum describes the different types of rubber bands that can be used for zoom rect selection
30 This enum describes the different types of rubber bands that can be used for zoom rect selection
32
31
33 \value NoRubberBand
32 \value NoRubberBand
34 \value VerticalRubberBand
33 \value VerticalRubberBand
35 \value HorizonalRubberBand
34 \value HorizonalRubberBand
36 \value RectangleRubberBand
35 \value RectangleRubberBand
37 */
36 */
38
37
39 /*!
38 /*!
40 \class QChartView
39 \class QChartView
41 \brief Standalone charting widget.
40 \brief Standalone charting widget.
42
41
43 QChartView is a standalone widget that can display charts. It does not require separate
42 QChartView is a standalone widget that can display charts. It does not require separate
44 QGraphicsScene to work. If you want to display a chart in your existing QGraphicsScene,
43 QGraphicsScene to work. If you want to display a chart in your existing QGraphicsScene,
45 you need to use the QChart (or QPolarChart) class instead.
44 you need to use the QChart (or QPolarChart) class instead.
46
45
47 \sa QChart, QPolarChart
46 \sa QChart, QPolarChart
48 */
47 */
49
48
50 QTCOMMERCIALCHART_BEGIN_NAMESPACE
49 QTCOMMERCIALCHART_BEGIN_NAMESPACE
51
50
52 /*!
51 /*!
53 Constructs a chartView object with parent \a parent.
52 Constructs a chartView object with parent \a parent.
54 */
53 */
55
54
56 QChartView::QChartView(QWidget *parent)
55 QChartView::QChartView(QWidget *parent)
57 : QGraphicsView(parent),
56 : QGraphicsView(parent),
58 d_ptr(new QChartViewPrivate(this))
57 d_ptr(new QChartViewPrivate(this))
59 {
58 {
60
59
61 }
60 }
62
61
63 /*!
62 /*!
64 Constructs a chartview object with parent \a parent to display a \a chart.
63 Constructs a chartview object with parent \a parent to display a \a chart.
65 Ownership of the \a chart is passed to chartview.
64 Ownership of the \a chart is passed to chartview.
66 */
65 */
67
66
68 QChartView::QChartView(QChart *chart, QWidget *parent)
67 QChartView::QChartView(QChart *chart, QWidget *parent)
69 : QGraphicsView(parent),
68 : QGraphicsView(parent),
70 d_ptr(new QChartViewPrivate(this, chart))
69 d_ptr(new QChartViewPrivate(this, chart))
71 {
70 {
72
71
73 }
72 }
74
73
75
74
76 /*!
75 /*!
77 Destroys the chartview object and the associated chart.
76 Destroys the chartview object and the associated chart.
78 */
77 */
79 QChartView::~QChartView()
78 QChartView::~QChartView()
80 {
79 {
81 }
80 }
82
81
83 /*!
82 /*!
84 Returns the pointer to the associated chart.
83 Returns the pointer to the associated chart.
85 */
84 */
86 QChart *QChartView::chart() const
85 QChart *QChartView::chart() const
87 {
86 {
88 return d_ptr->m_chart;
87 return d_ptr->m_chart;
89 }
88 }
90
89
91 /*!
90 /*!
92 Sets the current chart to \a chart. Ownership of the new chart is passed to chartview
91 Sets the current chart to \a chart. Ownership of the new chart is passed to chartview
93 and ownership of the previous chart is released.
92 and ownership of the previous chart is released.
94
93
95 To avoid memory leaks users need to make sure the previous chart is deleted.
94 To avoid memory leaks users need to make sure the previous chart is deleted.
96 */
95 */
97
96
98 void QChartView::setChart(QChart *chart)
97 void QChartView::setChart(QChart *chart)
99 {
98 {
100 d_ptr->setChart(chart);
99 d_ptr->setChart(chart);
101 }
100 }
102
101
103 /*!
102 /*!
104 Sets the rubber band flags to \a rubberBand.
103 Sets the rubber band flags to \a rubberBand.
105 Selected flags determine the way zooming is performed.
104 Selected flags determine the way zooming is performed.
106
105
107 \note Rubber band zooming is not supported for polar charts.
106 \note Rubber band zooming is not supported for polar charts.
108 */
107 */
109 void QChartView::setRubberBand(const RubberBands &rubberBand)
108 void QChartView::setRubberBand(const RubberBands &rubberBand)
110 {
109 {
111 d_ptr->m_rubberBandFlags = rubberBand;
110 d_ptr->m_rubberBandFlags = rubberBand;
112
111
113 if (!d_ptr->m_rubberBandFlags) {
112 if (!d_ptr->m_rubberBandFlags) {
114 delete d_ptr->m_rubberBand;
113 delete d_ptr->m_rubberBand;
115 d_ptr->m_rubberBand = 0;
114 d_ptr->m_rubberBand = 0;
116 return;
115 return;
117 }
116 }
118
117
119 if (!d_ptr->m_rubberBand) {
118 if (!d_ptr->m_rubberBand) {
120 d_ptr->m_rubberBand = new QRubberBand(QRubberBand::Rectangle, this);
119 d_ptr->m_rubberBand = new QRubberBand(QRubberBand::Rectangle, this);
121 d_ptr->m_rubberBand->setEnabled(true);
120 d_ptr->m_rubberBand->setEnabled(true);
122 }
121 }
123 }
122 }
124
123
125 /*!
124 /*!
126 Returns the rubber band flags that are currently being used by the widget.
125 Returns the rubber band flags that are currently being used by the widget.
127 */
126 */
128 QChartView::RubberBands QChartView::rubberBand() const
127 QChartView::RubberBands QChartView::rubberBand() const
129 {
128 {
130 return d_ptr->m_rubberBandFlags;
129 return d_ptr->m_rubberBandFlags;
131 }
130 }
132
131
133 /*!
132 /*!
134 If Left mouse button is pressed and the rubber band is enabled the \a event is accepted and the rubber band is displayed on the screen allowing the user to select the zoom area.
133 If Left mouse button is pressed and the rubber band is enabled the \a event is accepted and the rubber band is displayed on the screen allowing the user to select the zoom area.
135 If different mouse button is pressed and/or the rubber band is disabled then the \a event is passed to QGraphicsView::mousePressEvent() implementation.
134 If different mouse button is pressed and/or the rubber band is disabled then the \a event is passed to QGraphicsView::mousePressEvent() implementation.
136 */
135 */
137 void QChartView::mousePressEvent(QMouseEvent *event)
136 void QChartView::mousePressEvent(QMouseEvent *event)
138 {
137 {
139 if (d_ptr->m_rubberBand && d_ptr->m_rubberBand->isEnabled() && event->button() == Qt::LeftButton) {
138 if (d_ptr->m_rubberBand && d_ptr->m_rubberBand->isEnabled() && event->button() == Qt::LeftButton) {
140
139
141 QRectF plotArea = d_ptr->m_chart->plotArea();
140 QRectF plotArea = d_ptr->m_chart->plotArea();
142
141
143 if (plotArea.contains(event->pos())) {
142 if (plotArea.contains(event->pos())) {
144 d_ptr->m_rubberBandOrigin = event->pos();
143 d_ptr->m_rubberBandOrigin = event->pos();
145 d_ptr->m_rubberBand->setGeometry(QRect(d_ptr->m_rubberBandOrigin, QSize()));
144 d_ptr->m_rubberBand->setGeometry(QRect(d_ptr->m_rubberBandOrigin, QSize()));
146 d_ptr->m_rubberBand->show();
145 d_ptr->m_rubberBand->show();
147 event->accept();
146 event->accept();
148 }
147 }
149 } else {
148 } else {
150 QGraphicsView::mousePressEvent(event);
149 QGraphicsView::mousePressEvent(event);
151 }
150 }
152 }
151 }
153
152
154 /*!
153 /*!
155 If the rubber band rectange has been displayed in pressEvent then \a event data is used to update the rubber band geometry.
154 If the rubber band rectange has been displayed in pressEvent then \a event data is used to update the rubber band geometry.
156 Otherwise the default QGraphicsView::mouseMoveEvent implementation is called.
155 Otherwise the default QGraphicsView::mouseMoveEvent implementation is called.
157 */
156 */
158 void QChartView::mouseMoveEvent(QMouseEvent *event)
157 void QChartView::mouseMoveEvent(QMouseEvent *event)
159 {
158 {
160 if (d_ptr->m_rubberBand && d_ptr->m_rubberBand->isVisible()) {
159 if (d_ptr->m_rubberBand && d_ptr->m_rubberBand->isVisible()) {
161 QRect rect = d_ptr->m_chart->plotArea().toRect();
160 QRect rect = d_ptr->m_chart->plotArea().toRect();
162 int width = event->pos().x() - d_ptr->m_rubberBandOrigin.x();
161 int width = event->pos().x() - d_ptr->m_rubberBandOrigin.x();
163 int height = event->pos().y() - d_ptr->m_rubberBandOrigin.y();
162 int height = event->pos().y() - d_ptr->m_rubberBandOrigin.y();
164 if (!d_ptr->m_rubberBandFlags.testFlag(VerticalRubberBand)) {
163 if (!d_ptr->m_rubberBandFlags.testFlag(VerticalRubberBand)) {
165 d_ptr->m_rubberBandOrigin.setY(rect.top());
164 d_ptr->m_rubberBandOrigin.setY(rect.top());
166 height = rect.height();
165 height = rect.height();
167 }
166 }
168 if (!d_ptr->m_rubberBandFlags.testFlag(HorizonalRubberBand)) {
167 if (!d_ptr->m_rubberBandFlags.testFlag(HorizonalRubberBand)) {
169 d_ptr->m_rubberBandOrigin.setX(rect.left());
168 d_ptr->m_rubberBandOrigin.setX(rect.left());
170 width = rect.width();
169 width = rect.width();
171 }
170 }
172 d_ptr->m_rubberBand->setGeometry(QRect(d_ptr->m_rubberBandOrigin.x(), d_ptr->m_rubberBandOrigin.y(), width, height).normalized());
171 d_ptr->m_rubberBand->setGeometry(QRect(d_ptr->m_rubberBandOrigin.x(), d_ptr->m_rubberBandOrigin.y(), width, height).normalized());
173 } else {
172 } else {
174 QGraphicsView::mouseMoveEvent(event);
173 QGraphicsView::mouseMoveEvent(event);
175 }
174 }
176 }
175 }
177
176
178 /*!
177 /*!
179 If left mouse button is released and the rubber band is enabled then \a event is accepted and
178 If left mouse button is released and the rubber band is enabled then \a event is accepted and
180 the view is zoomed into the rect specified by the rubber band.
179 the view is zoomed into the rect specified by the rubber band.
181 If it is a right mouse button \a event then the rubber band is dismissed and the zoom is canceled.
180 If it is a right mouse button \a event then the rubber band is dismissed and the zoom is canceled.
182 */
181 */
183 void QChartView::mouseReleaseEvent(QMouseEvent *event)
182 void QChartView::mouseReleaseEvent(QMouseEvent *event)
184 {
183 {
185 if (d_ptr->m_rubberBand) {
184 if (d_ptr->m_rubberBand) {
186 if (event->button() == Qt::LeftButton && d_ptr->m_rubberBand->isVisible()) {
185 if (event->button() == Qt::LeftButton && d_ptr->m_rubberBand->isVisible()) {
187 d_ptr->m_rubberBand->hide();
186 d_ptr->m_rubberBand->hide();
188 QRectF rect = d_ptr->m_rubberBand->geometry();
187 QRectF rect = d_ptr->m_rubberBand->geometry();
189 // Since plotArea uses QRectF and rubberband uses QRect, we can't just blindly use
188 // Since plotArea uses QRectF and rubberband uses QRect, we can't just blindly use
190 // rubberband's dimensions for vertical and horizontal rubberbands, where one
189 // rubberband's dimensions for vertical and horizontal rubberbands, where one
191 // dimension must match the corresponding plotArea dimension exactly.
190 // dimension must match the corresponding plotArea dimension exactly.
192 if (d_ptr->m_rubberBandFlags == VerticalRubberBand) {
191 if (d_ptr->m_rubberBandFlags == VerticalRubberBand) {
193 rect.setX(d_ptr->m_chart->plotArea().x());
192 rect.setX(d_ptr->m_chart->plotArea().x());
194 rect.setWidth(d_ptr->m_chart->plotArea().width());
193 rect.setWidth(d_ptr->m_chart->plotArea().width());
195 } else if (d_ptr->m_rubberBandFlags == HorizonalRubberBand) {
194 } else if (d_ptr->m_rubberBandFlags == HorizonalRubberBand) {
196 rect.setY(d_ptr->m_chart->plotArea().y());
195 rect.setY(d_ptr->m_chart->plotArea().y());
197 rect.setHeight(d_ptr->m_chart->plotArea().height());
196 rect.setHeight(d_ptr->m_chart->plotArea().height());
198 }
197 }
199 d_ptr->m_chart->zoomIn(rect);
198 d_ptr->m_chart->zoomIn(rect);
200 event->accept();
199 event->accept();
201 }
200 }
202
201
203 if (event->button() == Qt::RightButton) {
202 if (event->button() == Qt::RightButton) {
204 d_ptr->m_chart->zoomOut();
203 d_ptr->m_chart->zoomOut();
205 event->accept();
204 event->accept();
206 }
205 }
207 } else {
206 } else {
208 QGraphicsView::mouseReleaseEvent(event);
207 QGraphicsView::mouseReleaseEvent(event);
209 }
208 }
210 }
209 }
211
210
212 /*!
211 /*!
213 Resizes and updates the chart area using the \a event data
212 Resizes and updates the chart area using the \a event data
214 */
213 */
215 void QChartView::resizeEvent(QResizeEvent *event)
214 void QChartView::resizeEvent(QResizeEvent *event)
216 {
215 {
217 QGraphicsView::resizeEvent(event);
216 QGraphicsView::resizeEvent(event);
218 d_ptr->resize();
217 d_ptr->resize();
219 }
218 }
220
219
221 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
220 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
222
221
223 QChartViewPrivate::QChartViewPrivate(QChartView *q, QChart *chart)
222 QChartViewPrivate::QChartViewPrivate(QChartView *q, QChart *chart)
224 : q_ptr(q),
223 : q_ptr(q),
225 m_scene(new QGraphicsScene(q)),
224 m_scene(new QGraphicsScene(q)),
226 m_chart(chart),
225 m_chart(chart),
227 m_rubberBand(0),
226 m_rubberBand(0),
228 m_rubberBandFlags(QChartView::NoRubberBand)
227 m_rubberBandFlags(QChartView::NoRubberBand)
229 {
228 {
230 q_ptr->setFrameShape(QFrame::NoFrame);
229 q_ptr->setFrameShape(QFrame::NoFrame);
231 q_ptr->setBackgroundRole(QPalette::Window);
230 q_ptr->setBackgroundRole(QPalette::Window);
232 q_ptr->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
231 q_ptr->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
233 q_ptr->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
232 q_ptr->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
234 q_ptr->setScene(m_scene);
233 q_ptr->setScene(m_scene);
235 q_ptr->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
234 q_ptr->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
236 if (!m_chart)
235 if (!m_chart)
237 m_chart = new QChart();
236 m_chart = new QChart();
238 m_scene->addItem(m_chart);
237 m_scene->addItem(m_chart);
239 }
238 }
240
239
241 QChartViewPrivate::~QChartViewPrivate()
240 QChartViewPrivate::~QChartViewPrivate()
242 {
241 {
243 }
242 }
244
243
245 void QChartViewPrivate::setChart(QChart *chart)
244 void QChartViewPrivate::setChart(QChart *chart)
246 {
245 {
247 Q_ASSERT(chart);
246 Q_ASSERT(chart);
248
247
249 if (m_chart == chart)
248 if (m_chart == chart)
250 return;
249 return;
251
250
252 if (m_chart)
251 if (m_chart)
253 m_scene->removeItem(m_chart);
252 m_scene->removeItem(m_chart);
254
253
255 m_chart = chart;
254 m_chart = chart;
256 m_scene->addItem(m_chart);
255 m_scene->addItem(m_chart);
257
256
258 resize();
257 resize();
259 }
258 }
260
259
261 const qreal rad2deg(57.2957795);
262
263 void QChartViewPrivate::resize()
260 void QChartViewPrivate::resize()
264 {
261 {
265 // Flip chart width and height if the view has been rotated
262 // Fit the chart into view if it has been rotated
266 // more than 45 degrees from the horizontal so it fits better into the view.
263 qreal sinA = qAbs(q_ptr->transform().m21());
267 qreal angle = qAcos(q_ptr->transform().m11()) * rad2deg;
264 qreal cosA = qAbs(q_ptr->transform().m11());
268 QSize chartSize = q_ptr->size();
265 QSize chartSize = q_ptr->size();
269
266
270 if (angle > 45.0 && angle < 135.0) {
267 if (sinA == 1.0) {
271 chartSize.setHeight(q_ptr->size().width());
268 chartSize.setHeight(q_ptr->size().width());
272 chartSize.setWidth(q_ptr->size().height());
269 chartSize.setWidth(q_ptr->size().height());
270 } else if (sinA != 0.0) {
271 // Non-90 degree rotation, find largest square chart that can fit into the view.
272 qreal minDimension = qMin(q_ptr->size().width(), q_ptr->size().height());
273 qreal h = (minDimension - (minDimension / ((sinA / cosA) + 1.0))) / sinA;
274 chartSize.setHeight(h);
275 chartSize.setWidth(h);
273 }
276 }
274
277
275 m_chart->resize(chartSize);
278 m_chart->resize(chartSize);
276 q_ptr->setMinimumSize(m_chart->minimumSize().toSize());
279 q_ptr->setMinimumSize(m_chart->minimumSize().toSize());
277 q_ptr->setSceneRect(m_chart->geometry());
280 q_ptr->setSceneRect(m_chart->geometry());
278 }
281 }
279
282
280 #include "moc_qchartview.cpp"
283 #include "moc_qchartview.cpp"
281
284
282 QTCOMMERCIALCHART_END_NAMESPACE
285 QTCOMMERCIALCHART_END_NAMESPACE
General Comments 0
You need to be logged in to leave comments. Login now