##// END OF EJS Templates
Fix mouse event handling with RubberBand...
Titta Heikkala -
r2609:cff0f629c1c4
parent child
Show More
@@ -1,301 +1,298
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 Enterprise Charts Add-on.
7 ** This file is part of the Qt Enterprise Charts Add-on.
8 **
8 **
9 ** $QT_BEGIN_LICENSE$
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Enterprise licenses may use this file in
10 ** Licensees holding valid Qt Enterprise licenses may use this file in
11 ** accordance with the Qt Enterprise License Agreement provided with the
11 ** accordance with the Qt Enterprise 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 QRectF plotArea = d_ptr->m_chart->plotArea();
139
139 if (d_ptr->m_rubberBand && d_ptr->m_rubberBand->isEnabled()
140 QRectF plotArea = d_ptr->m_chart->plotArea();
140 && event->button() == Qt::LeftButton && plotArea.contains(event->pos())) {
141
141 d_ptr->m_rubberBandOrigin = event->pos();
142 if (plotArea.contains(event->pos())) {
142 d_ptr->m_rubberBand->setGeometry(QRect(d_ptr->m_rubberBandOrigin, QSize()));
143 d_ptr->m_rubberBandOrigin = event->pos();
143 d_ptr->m_rubberBand->show();
144 d_ptr->m_rubberBand->setGeometry(QRect(d_ptr->m_rubberBandOrigin, QSize()));
144 event->accept();
145 d_ptr->m_rubberBand->show();
146 event->accept();
147 }
148 } else {
145 } else {
149 QGraphicsView::mousePressEvent(event);
146 QGraphicsView::mousePressEvent(event);
150 }
147 }
151 }
148 }
152
149
153 /*!
150 /*!
154 If the rubber band rectange has been displayed in pressEvent then \a event data is used to update the rubber band geometry.
151 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.
152 Otherwise the default QGraphicsView::mouseMoveEvent implementation is called.
156 */
153 */
157 void QChartView::mouseMoveEvent(QMouseEvent *event)
154 void QChartView::mouseMoveEvent(QMouseEvent *event)
158 {
155 {
159 if (d_ptr->m_rubberBand && d_ptr->m_rubberBand->isVisible()) {
156 if (d_ptr->m_rubberBand && d_ptr->m_rubberBand->isVisible()) {
160 QRect rect = d_ptr->m_chart->plotArea().toRect();
157 QRect rect = d_ptr->m_chart->plotArea().toRect();
161 int width = event->pos().x() - d_ptr->m_rubberBandOrigin.x();
158 int width = event->pos().x() - d_ptr->m_rubberBandOrigin.x();
162 int height = event->pos().y() - d_ptr->m_rubberBandOrigin.y();
159 int height = event->pos().y() - d_ptr->m_rubberBandOrigin.y();
163 if (!d_ptr->m_rubberBandFlags.testFlag(VerticalRubberBand)) {
160 if (!d_ptr->m_rubberBandFlags.testFlag(VerticalRubberBand)) {
164 d_ptr->m_rubberBandOrigin.setY(rect.top());
161 d_ptr->m_rubberBandOrigin.setY(rect.top());
165 height = rect.height();
162 height = rect.height();
166 }
163 }
167 if (!d_ptr->m_rubberBandFlags.testFlag(HorizonalRubberBand)) {
164 if (!d_ptr->m_rubberBandFlags.testFlag(HorizonalRubberBand)) {
168 d_ptr->m_rubberBandOrigin.setX(rect.left());
165 d_ptr->m_rubberBandOrigin.setX(rect.left());
169 width = rect.width();
166 width = rect.width();
170 }
167 }
171 d_ptr->m_rubberBand->setGeometry(QRect(d_ptr->m_rubberBandOrigin.x(), d_ptr->m_rubberBandOrigin.y(), width, height).normalized());
168 d_ptr->m_rubberBand->setGeometry(QRect(d_ptr->m_rubberBandOrigin.x(), d_ptr->m_rubberBandOrigin.y(), width, height).normalized());
172 } else {
169 } else {
173 QGraphicsView::mouseMoveEvent(event);
170 QGraphicsView::mouseMoveEvent(event);
174 }
171 }
175 }
172 }
176
173
177 /*!
174 /*!
178 If left mouse button is released and the rubber band is enabled then \a event is accepted and
175 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.
176 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.
177 If it is a right mouse button \a event then the view is zoomed out.
181 */
178 */
182 void QChartView::mouseReleaseEvent(QMouseEvent *event)
179 void QChartView::mouseReleaseEvent(QMouseEvent *event)
183 {
180 {
184 if (d_ptr->m_rubberBand) {
181 if (d_ptr->m_rubberBand && d_ptr->m_rubberBand->isVisible()) {
185 if (event->button() == Qt::LeftButton && d_ptr->m_rubberBand->isVisible()) {
182 if (event->button() == Qt::LeftButton) {
186 d_ptr->m_rubberBand->hide();
183 d_ptr->m_rubberBand->hide();
187 QRectF rect = d_ptr->m_rubberBand->geometry();
184 QRectF rect = d_ptr->m_rubberBand->geometry();
188 // Since plotArea uses QRectF and rubberband uses QRect, we can't just blindly use
185 // 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
186 // rubberband's dimensions for vertical and horizontal rubberbands, where one
190 // dimension must match the corresponding plotArea dimension exactly.
187 // dimension must match the corresponding plotArea dimension exactly.
191 if (d_ptr->m_rubberBandFlags == VerticalRubberBand) {
188 if (d_ptr->m_rubberBandFlags == VerticalRubberBand) {
192 rect.setX(d_ptr->m_chart->plotArea().x());
189 rect.setX(d_ptr->m_chart->plotArea().x());
193 rect.setWidth(d_ptr->m_chart->plotArea().width());
190 rect.setWidth(d_ptr->m_chart->plotArea().width());
194 } else if (d_ptr->m_rubberBandFlags == HorizonalRubberBand) {
191 } else if (d_ptr->m_rubberBandFlags == HorizonalRubberBand) {
195 rect.setY(d_ptr->m_chart->plotArea().y());
192 rect.setY(d_ptr->m_chart->plotArea().y());
196 rect.setHeight(d_ptr->m_chart->plotArea().height());
193 rect.setHeight(d_ptr->m_chart->plotArea().height());
197 }
194 }
198 d_ptr->m_chart->zoomIn(rect);
195 d_ptr->m_chart->zoomIn(rect);
199 event->accept();
196 event->accept();
200 }
197 }
201
198
202 if (event->button() == Qt::RightButton) {
199 if (event->button() == Qt::RightButton) {
203 // If vertical or horizontal rubberband mode, restrict zoom out to specified axis.
200 // 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
201 // Since there is no suitable API for that, use zoomIn with rect bigger than the
205 // plot area.
202 // plot area.
206 if (d_ptr->m_rubberBandFlags == VerticalRubberBand
203 if (d_ptr->m_rubberBandFlags == VerticalRubberBand
207 || d_ptr->m_rubberBandFlags == HorizonalRubberBand) {
204 || d_ptr->m_rubberBandFlags == HorizonalRubberBand) {
208 QRectF rect = d_ptr->m_chart->plotArea();
205 QRectF rect = d_ptr->m_chart->plotArea();
209 if (d_ptr->m_rubberBandFlags == VerticalRubberBand) {
206 if (d_ptr->m_rubberBandFlags == VerticalRubberBand) {
210 qreal adjustment = rect.height() / 2;
207 qreal adjustment = rect.height() / 2;
211 rect.adjust(0, -adjustment, 0, adjustment);
208 rect.adjust(0, -adjustment, 0, adjustment);
212 } else if (d_ptr->m_rubberBandFlags == HorizonalRubberBand) {
209 } else if (d_ptr->m_rubberBandFlags == HorizonalRubberBand) {
213 qreal adjustment = rect.width() / 2;
210 qreal adjustment = rect.width() / 2;
214 rect.adjust(-adjustment, 0, adjustment, 0);
211 rect.adjust(-adjustment, 0, adjustment, 0);
215 }
212 }
216 d_ptr->m_chart->zoomIn(rect);
213 d_ptr->m_chart->zoomIn(rect);
217 } else {
214 } else {
218 d_ptr->m_chart->zoomOut();
215 d_ptr->m_chart->zoomOut();
219 }
216 }
220 event->accept();
217 event->accept();
221 }
218 }
222 } else {
219 } else {
223 QGraphicsView::mouseReleaseEvent(event);
220 QGraphicsView::mouseReleaseEvent(event);
224 }
221 }
225 }
222 }
226
223
227 /*!
224 /*!
228 Resizes and updates the chart area using the \a event data
225 Resizes and updates the chart area using the \a event data
229 */
226 */
230 void QChartView::resizeEvent(QResizeEvent *event)
227 void QChartView::resizeEvent(QResizeEvent *event)
231 {
228 {
232 QGraphicsView::resizeEvent(event);
229 QGraphicsView::resizeEvent(event);
233 d_ptr->resize();
230 d_ptr->resize();
234 }
231 }
235
232
236 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
233 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
237
234
238 QChartViewPrivate::QChartViewPrivate(QChartView *q, QChart *chart)
235 QChartViewPrivate::QChartViewPrivate(QChartView *q, QChart *chart)
239 : q_ptr(q),
236 : q_ptr(q),
240 m_scene(new QGraphicsScene(q)),
237 m_scene(new QGraphicsScene(q)),
241 m_chart(chart),
238 m_chart(chart),
242 m_rubberBand(0),
239 m_rubberBand(0),
243 m_rubberBandFlags(QChartView::NoRubberBand)
240 m_rubberBandFlags(QChartView::NoRubberBand)
244 {
241 {
245 q_ptr->setFrameShape(QFrame::NoFrame);
242 q_ptr->setFrameShape(QFrame::NoFrame);
246 q_ptr->setBackgroundRole(QPalette::Window);
243 q_ptr->setBackgroundRole(QPalette::Window);
247 q_ptr->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
244 q_ptr->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
248 q_ptr->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
245 q_ptr->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
249 q_ptr->setScene(m_scene);
246 q_ptr->setScene(m_scene);
250 q_ptr->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
247 q_ptr->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
251 if (!m_chart)
248 if (!m_chart)
252 m_chart = new QChart();
249 m_chart = new QChart();
253 m_scene->addItem(m_chart);
250 m_scene->addItem(m_chart);
254 }
251 }
255
252
256 QChartViewPrivate::~QChartViewPrivate()
253 QChartViewPrivate::~QChartViewPrivate()
257 {
254 {
258 }
255 }
259
256
260 void QChartViewPrivate::setChart(QChart *chart)
257 void QChartViewPrivate::setChart(QChart *chart)
261 {
258 {
262 Q_ASSERT(chart);
259 Q_ASSERT(chart);
263
260
264 if (m_chart == chart)
261 if (m_chart == chart)
265 return;
262 return;
266
263
267 if (m_chart)
264 if (m_chart)
268 m_scene->removeItem(m_chart);
265 m_scene->removeItem(m_chart);
269
266
270 m_chart = chart;
267 m_chart = chart;
271 m_scene->addItem(m_chart);
268 m_scene->addItem(m_chart);
272
269
273 resize();
270 resize();
274 }
271 }
275
272
276 void QChartViewPrivate::resize()
273 void QChartViewPrivate::resize()
277 {
274 {
278 // Fit the chart into view if it has been rotated
275 // Fit the chart into view if it has been rotated
279 qreal sinA = qAbs(q_ptr->transform().m21());
276 qreal sinA = qAbs(q_ptr->transform().m21());
280 qreal cosA = qAbs(q_ptr->transform().m11());
277 qreal cosA = qAbs(q_ptr->transform().m11());
281 QSize chartSize = q_ptr->size();
278 QSize chartSize = q_ptr->size();
282
279
283 if (sinA == 1.0) {
280 if (sinA == 1.0) {
284 chartSize.setHeight(q_ptr->size().width());
281 chartSize.setHeight(q_ptr->size().width());
285 chartSize.setWidth(q_ptr->size().height());
282 chartSize.setWidth(q_ptr->size().height());
286 } else if (sinA != 0.0) {
283 } else if (sinA != 0.0) {
287 // Non-90 degree rotation, find largest square chart that can fit into the view.
284 // Non-90 degree rotation, find largest square chart that can fit into the view.
288 qreal minDimension = qMin(q_ptr->size().width(), q_ptr->size().height());
285 qreal minDimension = qMin(q_ptr->size().width(), q_ptr->size().height());
289 qreal h = (minDimension - (minDimension / ((sinA / cosA) + 1.0))) / sinA;
286 qreal h = (minDimension - (minDimension / ((sinA / cosA) + 1.0))) / sinA;
290 chartSize.setHeight(h);
287 chartSize.setHeight(h);
291 chartSize.setWidth(h);
288 chartSize.setWidth(h);
292 }
289 }
293
290
294 m_chart->resize(chartSize);
291 m_chart->resize(chartSize);
295 q_ptr->setMinimumSize(m_chart->minimumSize().toSize());
292 q_ptr->setMinimumSize(m_chart->minimumSize().toSize());
296 q_ptr->setSceneRect(m_chart->geometry());
293 q_ptr->setSceneRect(m_chart->geometry());
297 }
294 }
298
295
299 #include "moc_qchartview.cpp"
296 #include "moc_qchartview.cpp"
300
297
301 QTCOMMERCIALCHART_END_NAMESPACE
298 QTCOMMERCIALCHART_END_NAMESPACE
General Comments 0
You need to be logged in to leave comments. Login now