##// END OF EJS Templates
Fixed QChartView right click zoom out when zooming one axis...
Miikka Heikkinen -
r2546:1b110337eade
parent child
Show More
@@ -1,285 +1,301
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
26
27 /*!
27 /*!
28 \enum QChartView::RubberBand
28 \enum QChartView::RubberBand
29
29
30 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
31
31
32 \value NoRubberBand
32 \value NoRubberBand
33 \value VerticalRubberBand
33 \value VerticalRubberBand
34 \value HorizonalRubberBand
34 \value HorizonalRubberBand
35 \value RectangleRubberBand
35 \value RectangleRubberBand
36 */
36 */
37
37
38 /*!
38 /*!
39 \class QChartView
39 \class QChartView
40 \brief Standalone charting widget.
40 \brief Standalone charting widget.
41
41
42 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
43 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,
44 you need to use the QChart (or QPolarChart) class instead.
44 you need to use the QChart (or QPolarChart) class instead.
45
45
46 \sa QChart, QPolarChart
46 \sa QChart, QPolarChart
47 */
47 */
48
48
49 QTCOMMERCIALCHART_BEGIN_NAMESPACE
49 QTCOMMERCIALCHART_BEGIN_NAMESPACE
50
50
51 /*!
51 /*!
52 Constructs a chartView object with parent \a parent.
52 Constructs a chartView object with parent \a parent.
53 */
53 */
54
54
55 QChartView::QChartView(QWidget *parent)
55 QChartView::QChartView(QWidget *parent)
56 : QGraphicsView(parent),
56 : QGraphicsView(parent),
57 d_ptr(new QChartViewPrivate(this))
57 d_ptr(new QChartViewPrivate(this))
58 {
58 {
59
59
60 }
60 }
61
61
62 /*!
62 /*!
63 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.
64 Ownership of the \a chart is passed to chartview.
64 Ownership of the \a chart is passed to chartview.
65 */
65 */
66
66
67 QChartView::QChartView(QChart *chart, QWidget *parent)
67 QChartView::QChartView(QChart *chart, QWidget *parent)
68 : QGraphicsView(parent),
68 : QGraphicsView(parent),
69 d_ptr(new QChartViewPrivate(this, chart))
69 d_ptr(new QChartViewPrivate(this, chart))
70 {
70 {
71
71
72 }
72 }
73
73
74
74
75 /*!
75 /*!
76 Destroys the chartview object and the associated chart.
76 Destroys the chartview object and the associated chart.
77 */
77 */
78 QChartView::~QChartView()
78 QChartView::~QChartView()
79 {
79 {
80 }
80 }
81
81
82 /*!
82 /*!
83 Returns the pointer to the associated chart.
83 Returns the pointer to the associated chart.
84 */
84 */
85 QChart *QChartView::chart() const
85 QChart *QChartView::chart() const
86 {
86 {
87 return d_ptr->m_chart;
87 return d_ptr->m_chart;
88 }
88 }
89
89
90 /*!
90 /*!
91 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
92 and ownership of the previous chart is released.
92 and ownership of the previous chart is released.
93
93
94 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.
95 */
95 */
96
96
97 void QChartView::setChart(QChart *chart)
97 void QChartView::setChart(QChart *chart)
98 {
98 {
99 d_ptr->setChart(chart);
99 d_ptr->setChart(chart);
100 }
100 }
101
101
102 /*!
102 /*!
103 Sets the rubber band flags to \a rubberBand.
103 Sets the rubber band flags to \a rubberBand.
104 Selected flags determine the way zooming is performed.
104 Selected flags determine the way zooming is performed.
105
105
106 \note Rubber band zooming is not supported for polar charts.
106 \note Rubber band zooming is not supported for polar charts.
107 */
107 */
108 void QChartView::setRubberBand(const RubberBands &rubberBand)
108 void QChartView::setRubberBand(const RubberBands &rubberBand)
109 {
109 {
110 d_ptr->m_rubberBandFlags = rubberBand;
110 d_ptr->m_rubberBandFlags = rubberBand;
111
111
112 if (!d_ptr->m_rubberBandFlags) {
112 if (!d_ptr->m_rubberBandFlags) {
113 delete d_ptr->m_rubberBand;
113 delete d_ptr->m_rubberBand;
114 d_ptr->m_rubberBand = 0;
114 d_ptr->m_rubberBand = 0;
115 return;
115 return;
116 }
116 }
117
117
118 if (!d_ptr->m_rubberBand) {
118 if (!d_ptr->m_rubberBand) {
119 d_ptr->m_rubberBand = new QRubberBand(QRubberBand::Rectangle, this);
119 d_ptr->m_rubberBand = new QRubberBand(QRubberBand::Rectangle, this);
120 d_ptr->m_rubberBand->setEnabled(true);
120 d_ptr->m_rubberBand->setEnabled(true);
121 }
121 }
122 }
122 }
123
123
124 /*!
124 /*!
125 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.
126 */
126 */
127 QChartView::RubberBands QChartView::rubberBand() const
127 QChartView::RubberBands QChartView::rubberBand() const
128 {
128 {
129 return d_ptr->m_rubberBandFlags;
129 return d_ptr->m_rubberBandFlags;
130 }
130 }
131
131
132 /*!
132 /*!
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.
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.
134 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.
135 */
135 */
136 void QChartView::mousePressEvent(QMouseEvent *event)
136 void QChartView::mousePressEvent(QMouseEvent *event)
137 {
137 {
138 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) {
139
139
140 QRectF plotArea = d_ptr->m_chart->plotArea();
140 QRectF plotArea = d_ptr->m_chart->plotArea();
141
141
142 if (plotArea.contains(event->pos())) {
142 if (plotArea.contains(event->pos())) {
143 d_ptr->m_rubberBandOrigin = event->pos();
143 d_ptr->m_rubberBandOrigin = event->pos();
144 d_ptr->m_rubberBand->setGeometry(QRect(d_ptr->m_rubberBandOrigin, QSize()));
144 d_ptr->m_rubberBand->setGeometry(QRect(d_ptr->m_rubberBandOrigin, QSize()));
145 d_ptr->m_rubberBand->show();
145 d_ptr->m_rubberBand->show();
146 event->accept();
146 event->accept();
147 }
147 }
148 } else {
148 } else {
149 QGraphicsView::mousePressEvent(event);
149 QGraphicsView::mousePressEvent(event);
150 }
150 }
151 }
151 }
152
152
153 /*!
153 /*!
154 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.
155 Otherwise the default QGraphicsView::mouseMoveEvent implementation is called.
155 Otherwise the default QGraphicsView::mouseMoveEvent implementation is called.
156 */
156 */
157 void QChartView::mouseMoveEvent(QMouseEvent *event)
157 void QChartView::mouseMoveEvent(QMouseEvent *event)
158 {
158 {
159 if (d_ptr->m_rubberBand && d_ptr->m_rubberBand->isVisible()) {
159 if (d_ptr->m_rubberBand && d_ptr->m_rubberBand->isVisible()) {
160 QRect rect = d_ptr->m_chart->plotArea().toRect();
160 QRect rect = d_ptr->m_chart->plotArea().toRect();
161 int width = event->pos().x() - d_ptr->m_rubberBandOrigin.x();
161 int width = event->pos().x() - d_ptr->m_rubberBandOrigin.x();
162 int height = event->pos().y() - d_ptr->m_rubberBandOrigin.y();
162 int height = event->pos().y() - d_ptr->m_rubberBandOrigin.y();
163 if (!d_ptr->m_rubberBandFlags.testFlag(VerticalRubberBand)) {
163 if (!d_ptr->m_rubberBandFlags.testFlag(VerticalRubberBand)) {
164 d_ptr->m_rubberBandOrigin.setY(rect.top());
164 d_ptr->m_rubberBandOrigin.setY(rect.top());
165 height = rect.height();
165 height = rect.height();
166 }
166 }
167 if (!d_ptr->m_rubberBandFlags.testFlag(HorizonalRubberBand)) {
167 if (!d_ptr->m_rubberBandFlags.testFlag(HorizonalRubberBand)) {
168 d_ptr->m_rubberBandOrigin.setX(rect.left());
168 d_ptr->m_rubberBandOrigin.setX(rect.left());
169 width = rect.width();
169 width = rect.width();
170 }
170 }
171 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());
172 } else {
172 } else {
173 QGraphicsView::mouseMoveEvent(event);
173 QGraphicsView::mouseMoveEvent(event);
174 }
174 }
175 }
175 }
176
176
177 /*!
177 /*!
178 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
179 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.
180 If it is a right mouse button \a event then the view is zoomed out.
180 If it is a right mouse button \a event then the view is zoomed out.
181 */
181 */
182 void QChartView::mouseReleaseEvent(QMouseEvent *event)
182 void QChartView::mouseReleaseEvent(QMouseEvent *event)
183 {
183 {
184 if (d_ptr->m_rubberBand) {
184 if (d_ptr->m_rubberBand) {
185 if (event->button() == Qt::LeftButton && d_ptr->m_rubberBand->isVisible()) {
185 if (event->button() == Qt::LeftButton && d_ptr->m_rubberBand->isVisible()) {
186 d_ptr->m_rubberBand->hide();
186 d_ptr->m_rubberBand->hide();
187 QRectF rect = d_ptr->m_rubberBand->geometry();
187 QRectF rect = d_ptr->m_rubberBand->geometry();
188 // 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
189 // rubberband's dimensions for vertical and horizontal rubberbands, where one
189 // rubberband's dimensions for vertical and horizontal rubberbands, where one
190 // dimension must match the corresponding plotArea dimension exactly.
190 // dimension must match the corresponding plotArea dimension exactly.
191 if (d_ptr->m_rubberBandFlags == VerticalRubberBand) {
191 if (d_ptr->m_rubberBandFlags == VerticalRubberBand) {
192 rect.setX(d_ptr->m_chart->plotArea().x());
192 rect.setX(d_ptr->m_chart->plotArea().x());
193 rect.setWidth(d_ptr->m_chart->plotArea().width());
193 rect.setWidth(d_ptr->m_chart->plotArea().width());
194 } else if (d_ptr->m_rubberBandFlags == HorizonalRubberBand) {
194 } else if (d_ptr->m_rubberBandFlags == HorizonalRubberBand) {
195 rect.setY(d_ptr->m_chart->plotArea().y());
195 rect.setY(d_ptr->m_chart->plotArea().y());
196 rect.setHeight(d_ptr->m_chart->plotArea().height());
196 rect.setHeight(d_ptr->m_chart->plotArea().height());
197 }
197 }
198 d_ptr->m_chart->zoomIn(rect);
198 d_ptr->m_chart->zoomIn(rect);
199 event->accept();
199 event->accept();
200 }
200 }
201
201
202 if (event->button() == Qt::RightButton) {
202 if (event->button() == Qt::RightButton) {
203 d_ptr->m_chart->zoomOut();
203 // If vertical or horizontal rubberband mode, restrict zoom out to specified axis.
204 // Since there is no suitable API for that, use zoomIn with rect bigger than the
205 // plot area.
206 if (d_ptr->m_rubberBandFlags == VerticalRubberBand
207 || d_ptr->m_rubberBandFlags == HorizonalRubberBand) {
208 QRectF rect = d_ptr->m_chart->plotArea();
209 if (d_ptr->m_rubberBandFlags == VerticalRubberBand) {
210 qreal adjustment = rect.height() / 2;
211 rect.adjust(0, -adjustment, 0, adjustment);
212 } else if (d_ptr->m_rubberBandFlags == HorizonalRubberBand) {
213 qreal adjustment = rect.width() / 2;
214 rect.adjust(-adjustment, 0, adjustment, 0);
215 }
216 d_ptr->m_chart->zoomIn(rect);
217 } else {
218 d_ptr->m_chart->zoomOut();
219 }
204 event->accept();
220 event->accept();
205 }
221 }
206 } else {
222 } else {
207 QGraphicsView::mouseReleaseEvent(event);
223 QGraphicsView::mouseReleaseEvent(event);
208 }
224 }
209 }
225 }
210
226
211 /*!
227 /*!
212 Resizes and updates the chart area using the \a event data
228 Resizes and updates the chart area using the \a event data
213 */
229 */
214 void QChartView::resizeEvent(QResizeEvent *event)
230 void QChartView::resizeEvent(QResizeEvent *event)
215 {
231 {
216 QGraphicsView::resizeEvent(event);
232 QGraphicsView::resizeEvent(event);
217 d_ptr->resize();
233 d_ptr->resize();
218 }
234 }
219
235
220 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
236 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
221
237
222 QChartViewPrivate::QChartViewPrivate(QChartView *q, QChart *chart)
238 QChartViewPrivate::QChartViewPrivate(QChartView *q, QChart *chart)
223 : q_ptr(q),
239 : q_ptr(q),
224 m_scene(new QGraphicsScene(q)),
240 m_scene(new QGraphicsScene(q)),
225 m_chart(chart),
241 m_chart(chart),
226 m_rubberBand(0),
242 m_rubberBand(0),
227 m_rubberBandFlags(QChartView::NoRubberBand)
243 m_rubberBandFlags(QChartView::NoRubberBand)
228 {
244 {
229 q_ptr->setFrameShape(QFrame::NoFrame);
245 q_ptr->setFrameShape(QFrame::NoFrame);
230 q_ptr->setBackgroundRole(QPalette::Window);
246 q_ptr->setBackgroundRole(QPalette::Window);
231 q_ptr->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
247 q_ptr->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
232 q_ptr->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
248 q_ptr->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
233 q_ptr->setScene(m_scene);
249 q_ptr->setScene(m_scene);
234 q_ptr->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
250 q_ptr->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
235 if (!m_chart)
251 if (!m_chart)
236 m_chart = new QChart();
252 m_chart = new QChart();
237 m_scene->addItem(m_chart);
253 m_scene->addItem(m_chart);
238 }
254 }
239
255
240 QChartViewPrivate::~QChartViewPrivate()
256 QChartViewPrivate::~QChartViewPrivate()
241 {
257 {
242 }
258 }
243
259
244 void QChartViewPrivate::setChart(QChart *chart)
260 void QChartViewPrivate::setChart(QChart *chart)
245 {
261 {
246 Q_ASSERT(chart);
262 Q_ASSERT(chart);
247
263
248 if (m_chart == chart)
264 if (m_chart == chart)
249 return;
265 return;
250
266
251 if (m_chart)
267 if (m_chart)
252 m_scene->removeItem(m_chart);
268 m_scene->removeItem(m_chart);
253
269
254 m_chart = chart;
270 m_chart = chart;
255 m_scene->addItem(m_chart);
271 m_scene->addItem(m_chart);
256
272
257 resize();
273 resize();
258 }
274 }
259
275
260 void QChartViewPrivate::resize()
276 void QChartViewPrivate::resize()
261 {
277 {
262 // Fit the chart into view if it has been rotated
278 // Fit the chart into view if it has been rotated
263 qreal sinA = qAbs(q_ptr->transform().m21());
279 qreal sinA = qAbs(q_ptr->transform().m21());
264 qreal cosA = qAbs(q_ptr->transform().m11());
280 qreal cosA = qAbs(q_ptr->transform().m11());
265 QSize chartSize = q_ptr->size();
281 QSize chartSize = q_ptr->size();
266
282
267 if (sinA == 1.0) {
283 if (sinA == 1.0) {
268 chartSize.setHeight(q_ptr->size().width());
284 chartSize.setHeight(q_ptr->size().width());
269 chartSize.setWidth(q_ptr->size().height());
285 chartSize.setWidth(q_ptr->size().height());
270 } else if (sinA != 0.0) {
286 } else if (sinA != 0.0) {
271 // Non-90 degree rotation, find largest square chart that can fit into the view.
287 // 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());
288 qreal minDimension = qMin(q_ptr->size().width(), q_ptr->size().height());
273 qreal h = (minDimension - (minDimension / ((sinA / cosA) + 1.0))) / sinA;
289 qreal h = (minDimension - (minDimension / ((sinA / cosA) + 1.0))) / sinA;
274 chartSize.setHeight(h);
290 chartSize.setHeight(h);
275 chartSize.setWidth(h);
291 chartSize.setWidth(h);
276 }
292 }
277
293
278 m_chart->resize(chartSize);
294 m_chart->resize(chartSize);
279 q_ptr->setMinimumSize(m_chart->minimumSize().toSize());
295 q_ptr->setMinimumSize(m_chart->minimumSize().toSize());
280 q_ptr->setSceneRect(m_chart->geometry());
296 q_ptr->setSceneRect(m_chart->geometry());
281 }
297 }
282
298
283 #include "moc_qchartview.cpp"
299 #include "moc_qchartview.cpp"
284
300
285 QTCOMMERCIALCHART_END_NAMESPACE
301 QTCOMMERCIALCHART_END_NAMESPACE
General Comments 0
You need to be logged in to leave comments. Login now