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