1 | /* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
|
---|
2 | * Qwt Widget Library
|
---|
3 | * Copyright (C) 1997 Josef Wilgen
|
---|
4 | * Copyright (C) 2002 Uwe Rathmann
|
---|
5 | *
|
---|
6 | * This library is free software; you can redistribute it and/or
|
---|
7 | * modify it under the terms of the Qwt License, Version 1.0
|
---|
8 | *****************************************************************************/
|
---|
9 |
|
---|
10 | #include "qwt_magnifier.h"
|
---|
11 | #include "qwt_math.h"
|
---|
12 | #include <qevent.h>
|
---|
13 | #include <qwidget.h>
|
---|
14 |
|
---|
15 | class QwtMagnifier::PrivateData
|
---|
16 | {
|
---|
17 | public:
|
---|
18 | PrivateData():
|
---|
19 | isEnabled( false ),
|
---|
20 | wheelFactor( 0.9 ),
|
---|
21 | wheelButtonState( Qt::NoButton ),
|
---|
22 | mouseFactor( 0.95 ),
|
---|
23 | mouseButton( Qt::RightButton ),
|
---|
24 | mouseButtonState( Qt::NoButton ),
|
---|
25 | keyFactor( 0.9 ),
|
---|
26 | zoomInKey( Qt::Key_Plus ),
|
---|
27 | zoomOutKey( Qt::Key_Minus ),
|
---|
28 | zoomInKeyModifiers( Qt::NoModifier ),
|
---|
29 | zoomOutKeyModifiers( Qt::NoModifier ),
|
---|
30 | mousePressed( false )
|
---|
31 | {
|
---|
32 | }
|
---|
33 |
|
---|
34 | bool isEnabled;
|
---|
35 |
|
---|
36 | double wheelFactor;
|
---|
37 | int wheelButtonState;
|
---|
38 |
|
---|
39 | double mouseFactor;
|
---|
40 | int mouseButton;
|
---|
41 | int mouseButtonState;
|
---|
42 |
|
---|
43 | double keyFactor;
|
---|
44 | int zoomInKey;
|
---|
45 | int zoomOutKey;
|
---|
46 | int zoomInKeyModifiers;
|
---|
47 | int zoomOutKeyModifiers;
|
---|
48 |
|
---|
49 | bool mousePressed;
|
---|
50 | bool hasMouseTracking;
|
---|
51 | QPoint mousePos;
|
---|
52 | };
|
---|
53 |
|
---|
54 | /*!
|
---|
55 | Constructor
|
---|
56 | \param parent Widget to be magnified
|
---|
57 | */
|
---|
58 | QwtMagnifier::QwtMagnifier( QWidget *parent ):
|
---|
59 | QObject( parent )
|
---|
60 | {
|
---|
61 | d_data = new PrivateData();
|
---|
62 | setEnabled( true );
|
---|
63 | }
|
---|
64 |
|
---|
65 | //! Destructor
|
---|
66 | QwtMagnifier::~QwtMagnifier()
|
---|
67 | {
|
---|
68 | delete d_data;
|
---|
69 | }
|
---|
70 |
|
---|
71 | /*!
|
---|
72 | \brief En/disable the magnifier
|
---|
73 |
|
---|
74 | When enabled is true an event filter is installed for
|
---|
75 | the observed widget, otherwise the event filter is removed.
|
---|
76 |
|
---|
77 | \param on true or false
|
---|
78 | \sa isEnabled(), eventFilter()
|
---|
79 | */
|
---|
80 | void QwtMagnifier::setEnabled( bool on )
|
---|
81 | {
|
---|
82 | if ( d_data->isEnabled != on )
|
---|
83 | {
|
---|
84 | d_data->isEnabled = on;
|
---|
85 |
|
---|
86 | QObject *o = parent();
|
---|
87 | if ( o )
|
---|
88 | {
|
---|
89 | if ( d_data->isEnabled )
|
---|
90 | o->installEventFilter( this );
|
---|
91 | else
|
---|
92 | o->removeEventFilter( this );
|
---|
93 | }
|
---|
94 | }
|
---|
95 | }
|
---|
96 |
|
---|
97 | /*!
|
---|
98 | \return true when enabled, false otherwise
|
---|
99 | \sa setEnabled(), eventFilter()
|
---|
100 | */
|
---|
101 | bool QwtMagnifier::isEnabled() const
|
---|
102 | {
|
---|
103 | return d_data->isEnabled;
|
---|
104 | }
|
---|
105 |
|
---|
106 | /*!
|
---|
107 | \brief Change the wheel factor
|
---|
108 |
|
---|
109 | The wheel factor defines the ratio between the current range
|
---|
110 | on the parent widget and the zoomed range for each step of the wheel.
|
---|
111 | The default value is 0.9.
|
---|
112 |
|
---|
113 | \param factor Wheel factor
|
---|
114 | \sa wheelFactor(), setWheelButtonState(),
|
---|
115 | setMouseFactor(), setKeyFactor()
|
---|
116 | */
|
---|
117 | void QwtMagnifier::setWheelFactor( double factor )
|
---|
118 | {
|
---|
119 | d_data->wheelFactor = factor;
|
---|
120 | }
|
---|
121 |
|
---|
122 | /*!
|
---|
123 | \return Wheel factor
|
---|
124 | \sa setWheelFactor()
|
---|
125 | */
|
---|
126 | double QwtMagnifier::wheelFactor() const
|
---|
127 | {
|
---|
128 | return d_data->wheelFactor;
|
---|
129 | }
|
---|
130 |
|
---|
131 | /*!
|
---|
132 | Assign a mandatory button state for zooming in/out using the wheel.
|
---|
133 | The default button state is Qt::NoButton.
|
---|
134 |
|
---|
135 | \param buttonState Button state
|
---|
136 | \sa wheelButtonState()
|
---|
137 | */
|
---|
138 | void QwtMagnifier::setWheelButtonState( int buttonState )
|
---|
139 | {
|
---|
140 | d_data->wheelButtonState = buttonState;
|
---|
141 | }
|
---|
142 |
|
---|
143 | /*!
|
---|
144 | \return Wheel button state
|
---|
145 | \sa setWheelButtonState()
|
---|
146 | */
|
---|
147 | int QwtMagnifier::wheelButtonState() const
|
---|
148 | {
|
---|
149 | return d_data->wheelButtonState;
|
---|
150 | }
|
---|
151 |
|
---|
152 | /*!
|
---|
153 | \brief Change the mouse factor
|
---|
154 |
|
---|
155 | The mouse factor defines the ratio between the current range
|
---|
156 | on the parent widget and the zoomed range for each vertical mouse movement.
|
---|
157 | The default value is 0.95.
|
---|
158 |
|
---|
159 | \param factor Wheel factor
|
---|
160 | \sa mouseFactor(), setMouseButton(), setWheelFactor(), setKeyFactor()
|
---|
161 | */
|
---|
162 | void QwtMagnifier::setMouseFactor( double factor )
|
---|
163 | {
|
---|
164 | d_data->mouseFactor = factor;
|
---|
165 | }
|
---|
166 |
|
---|
167 | /*!
|
---|
168 | \return Mouse factor
|
---|
169 | \sa setMouseFactor()
|
---|
170 | */
|
---|
171 | double QwtMagnifier::mouseFactor() const
|
---|
172 | {
|
---|
173 | return d_data->mouseFactor;
|
---|
174 | }
|
---|
175 |
|
---|
176 | /*!
|
---|
177 | Assign the mouse button, that is used for zooming in/out.
|
---|
178 | The default value is Qt::RightButton.
|
---|
179 |
|
---|
180 | \param button Button
|
---|
181 | \param buttonState Button state
|
---|
182 | \sa getMouseButton()
|
---|
183 | */
|
---|
184 | void QwtMagnifier::setMouseButton( int button, int buttonState )
|
---|
185 | {
|
---|
186 | d_data->mouseButton = button;
|
---|
187 | d_data->mouseButtonState = buttonState;
|
---|
188 | }
|
---|
189 |
|
---|
190 | //! \sa setMouseButton()
|
---|
191 | void QwtMagnifier::getMouseButton(
|
---|
192 | int &button, int &buttonState ) const
|
---|
193 | {
|
---|
194 | button = d_data->mouseButton;
|
---|
195 | buttonState = d_data->mouseButtonState;
|
---|
196 | }
|
---|
197 |
|
---|
198 | /*!
|
---|
199 | \brief Change the key factor
|
---|
200 |
|
---|
201 | The key factor defines the ratio between the current range
|
---|
202 | on the parent widget and the zoomed range for each key press of
|
---|
203 | the zoom in/out keys. The default value is 0.9.
|
---|
204 |
|
---|
205 | \param factor Key factor
|
---|
206 | \sa keyFactor(), setZoomInKey(), setZoomOutKey(),
|
---|
207 | setWheelFactor, setMouseFactor()
|
---|
208 | */
|
---|
209 | void QwtMagnifier::setKeyFactor( double factor )
|
---|
210 | {
|
---|
211 | d_data->keyFactor = factor;
|
---|
212 | }
|
---|
213 |
|
---|
214 | /*!
|
---|
215 | \return Key factor
|
---|
216 | \sa setKeyFactor()
|
---|
217 | */
|
---|
218 | double QwtMagnifier::keyFactor() const
|
---|
219 | {
|
---|
220 | return d_data->keyFactor;
|
---|
221 | }
|
---|
222 |
|
---|
223 | /*!
|
---|
224 | Assign the key, that is used for zooming in.
|
---|
225 | The default combination is Qt::Key_Plus + Qt::NoModifier.
|
---|
226 |
|
---|
227 | \param key
|
---|
228 | \param modifiers
|
---|
229 | \sa getZoomInKey(), setZoomOutKey()
|
---|
230 | */
|
---|
231 | void QwtMagnifier::setZoomInKey( int key, int modifiers )
|
---|
232 | {
|
---|
233 | d_data->zoomInKey = key;
|
---|
234 | d_data->zoomInKeyModifiers = modifiers;
|
---|
235 | }
|
---|
236 |
|
---|
237 | //! \sa setZoomInKey()
|
---|
238 | void QwtMagnifier::getZoomInKey( int &key, int &modifiers ) const
|
---|
239 | {
|
---|
240 | key = d_data->zoomInKey;
|
---|
241 | modifiers = d_data->zoomInKeyModifiers;
|
---|
242 | }
|
---|
243 |
|
---|
244 | /*!
|
---|
245 | Assign the key, that is used for zooming out.
|
---|
246 | The default combination is Qt::Key_Minus + Qt::NoModifier.
|
---|
247 |
|
---|
248 | \param key
|
---|
249 | \param modifiers
|
---|
250 | \sa getZoomOutKey(), setZoomOutKey()
|
---|
251 | */
|
---|
252 | void QwtMagnifier::setZoomOutKey( int key, int modifiers )
|
---|
253 | {
|
---|
254 | d_data->zoomOutKey = key;
|
---|
255 | d_data->zoomOutKeyModifiers = modifiers;
|
---|
256 | }
|
---|
257 |
|
---|
258 | //! \sa setZoomOutKey()
|
---|
259 | void QwtMagnifier::getZoomOutKey( int &key, int &modifiers ) const
|
---|
260 | {
|
---|
261 | key = d_data->zoomOutKey;
|
---|
262 | modifiers = d_data->zoomOutKeyModifiers;
|
---|
263 | }
|
---|
264 |
|
---|
265 | /*!
|
---|
266 | \brief Event filter
|
---|
267 |
|
---|
268 | When isEnabled() the mouse events of the observed widget are filtered.
|
---|
269 |
|
---|
270 | \param object Object to be filtered
|
---|
271 | \param event Event
|
---|
272 |
|
---|
273 | \sa widgetMousePressEvent(), widgetMouseReleaseEvent(),
|
---|
274 | widgetMouseMoveEvent(), widgetWheelEvent(), widgetKeyPressEvent()
|
---|
275 | widgetKeyReleaseEvent()
|
---|
276 | */
|
---|
277 | bool QwtMagnifier::eventFilter( QObject *object, QEvent *event )
|
---|
278 | {
|
---|
279 | if ( object && object == parent() )
|
---|
280 | {
|
---|
281 | switch ( event->type() )
|
---|
282 | {
|
---|
283 | case QEvent::MouseButtonPress:
|
---|
284 | {
|
---|
285 | widgetMousePressEvent( ( QMouseEvent * )event );
|
---|
286 | break;
|
---|
287 | }
|
---|
288 | case QEvent::MouseMove:
|
---|
289 | {
|
---|
290 | widgetMouseMoveEvent( ( QMouseEvent * )event );
|
---|
291 | break;
|
---|
292 | }
|
---|
293 | case QEvent::MouseButtonRelease:
|
---|
294 | {
|
---|
295 | widgetMouseReleaseEvent( ( QMouseEvent * )event );
|
---|
296 | break;
|
---|
297 | }
|
---|
298 | case QEvent::Wheel:
|
---|
299 | {
|
---|
300 | widgetWheelEvent( ( QWheelEvent * )event );
|
---|
301 | break;
|
---|
302 | }
|
---|
303 | case QEvent::KeyPress:
|
---|
304 | {
|
---|
305 | widgetKeyPressEvent( ( QKeyEvent * )event );
|
---|
306 | break;
|
---|
307 | }
|
---|
308 | case QEvent::KeyRelease:
|
---|
309 | {
|
---|
310 | widgetKeyReleaseEvent( ( QKeyEvent * )event );
|
---|
311 | break;
|
---|
312 | }
|
---|
313 | default:;
|
---|
314 | }
|
---|
315 | }
|
---|
316 | return QObject::eventFilter( object, event );
|
---|
317 | }
|
---|
318 |
|
---|
319 | /*!
|
---|
320 | Handle a mouse press event for the observed widget.
|
---|
321 |
|
---|
322 | \param mouseEvent Mouse event
|
---|
323 | \sa eventFilter(), widgetMouseReleaseEvent(), widgetMouseMoveEvent()
|
---|
324 | */
|
---|
325 | void QwtMagnifier::widgetMousePressEvent( QMouseEvent *mouseEvent )
|
---|
326 | {
|
---|
327 | if ( ( mouseEvent->button() != d_data->mouseButton)
|
---|
328 | || parentWidget() == NULL )
|
---|
329 | {
|
---|
330 | return;
|
---|
331 | }
|
---|
332 |
|
---|
333 | if ( ( mouseEvent->modifiers() & Qt::KeyboardModifierMask ) !=
|
---|
334 | ( int )( d_data->mouseButtonState & Qt::KeyboardModifierMask ) )
|
---|
335 | {
|
---|
336 | return;
|
---|
337 | }
|
---|
338 |
|
---|
339 | d_data->hasMouseTracking = parentWidget()->hasMouseTracking();
|
---|
340 | parentWidget()->setMouseTracking( true );
|
---|
341 | d_data->mousePos = mouseEvent->pos();
|
---|
342 | d_data->mousePressed = true;
|
---|
343 | }
|
---|
344 |
|
---|
345 | /*!
|
---|
346 | Handle a mouse release event for the observed widget.
|
---|
347 |
|
---|
348 | \param mouseEvent Mouse event
|
---|
349 |
|
---|
350 | \sa eventFilter(), widgetMousePressEvent(), widgetMouseMoveEvent(),
|
---|
351 | */
|
---|
352 | void QwtMagnifier::widgetMouseReleaseEvent( QMouseEvent *mouseEvent )
|
---|
353 | {
|
---|
354 | Q_UNUSED( mouseEvent );
|
---|
355 |
|
---|
356 | if ( d_data->mousePressed && parentWidget() )
|
---|
357 | {
|
---|
358 | d_data->mousePressed = false;
|
---|
359 | parentWidget()->setMouseTracking( d_data->hasMouseTracking );
|
---|
360 | }
|
---|
361 | }
|
---|
362 |
|
---|
363 | /*!
|
---|
364 | Handle a mouse move event for the observed widget.
|
---|
365 |
|
---|
366 | \param mouseEvent Mouse event
|
---|
367 | \sa eventFilter(), widgetMousePressEvent(), widgetMouseReleaseEvent(),
|
---|
368 | */
|
---|
369 | void QwtMagnifier::widgetMouseMoveEvent( QMouseEvent *mouseEvent )
|
---|
370 | {
|
---|
371 | if ( !d_data->mousePressed )
|
---|
372 | return;
|
---|
373 |
|
---|
374 | const int dy = mouseEvent->pos().y() - d_data->mousePos.y();
|
---|
375 | if ( dy != 0 )
|
---|
376 | {
|
---|
377 | double f = d_data->mouseFactor;
|
---|
378 | if ( dy < 0 )
|
---|
379 | f = 1 / f;
|
---|
380 |
|
---|
381 | rescale( f );
|
---|
382 | }
|
---|
383 |
|
---|
384 | d_data->mousePos = mouseEvent->pos();
|
---|
385 | }
|
---|
386 |
|
---|
387 | /*!
|
---|
388 | Handle a wheel event for the observed widget.
|
---|
389 |
|
---|
390 | \param wheelEvent Wheel event
|
---|
391 | \sa eventFilter()
|
---|
392 | */
|
---|
393 | void QwtMagnifier::widgetWheelEvent( QWheelEvent *wheelEvent )
|
---|
394 | {
|
---|
395 | if ( ( wheelEvent->modifiers() & Qt::KeyboardModifierMask ) !=
|
---|
396 | ( int )( d_data->wheelButtonState & Qt::KeyboardModifierMask ) )
|
---|
397 | {
|
---|
398 | return;
|
---|
399 | }
|
---|
400 |
|
---|
401 | if ( d_data->wheelFactor != 0.0 )
|
---|
402 | {
|
---|
403 | /*
|
---|
404 | A positive delta indicates that the wheel was
|
---|
405 | rotated forwards away from the user; a negative
|
---|
406 | value indicates that the wheel was rotated
|
---|
407 | backwards toward the user.
|
---|
408 | Most mouse types work in steps of 15 degrees,
|
---|
409 | in which case the delta value is a multiple
|
---|
410 | of 120 (== 15 * 8).
|
---|
411 | */
|
---|
412 | double f = qPow( d_data->wheelFactor,
|
---|
413 | qAbs( wheelEvent->delta() / 120 ) );
|
---|
414 |
|
---|
415 | if ( wheelEvent->delta() > 0 )
|
---|
416 | f = 1 / f;
|
---|
417 |
|
---|
418 | rescale( f );
|
---|
419 | }
|
---|
420 | }
|
---|
421 |
|
---|
422 | /*!
|
---|
423 | Handle a key press event for the observed widget.
|
---|
424 |
|
---|
425 | \param keyEvent Key event
|
---|
426 | \sa eventFilter(), widgetKeyReleaseEvent()
|
---|
427 | */
|
---|
428 | void QwtMagnifier::widgetKeyPressEvent( QKeyEvent *keyEvent )
|
---|
429 | {
|
---|
430 | const int key = keyEvent->key();
|
---|
431 | const int state = keyEvent->modifiers();
|
---|
432 |
|
---|
433 | if ( key == d_data->zoomInKey &&
|
---|
434 | state == d_data->zoomInKeyModifiers )
|
---|
435 | {
|
---|
436 | rescale( d_data->keyFactor );
|
---|
437 | }
|
---|
438 | else if ( key == d_data->zoomOutKey &&
|
---|
439 | state == d_data->zoomOutKeyModifiers )
|
---|
440 | {
|
---|
441 | rescale( 1.0 / d_data->keyFactor );
|
---|
442 | }
|
---|
443 | }
|
---|
444 |
|
---|
445 | /*!
|
---|
446 | Handle a key release event for the observed widget.
|
---|
447 |
|
---|
448 | \param keyEvent Key event
|
---|
449 | \sa eventFilter(), widgetKeyReleaseEvent()
|
---|
450 | */
|
---|
451 | void QwtMagnifier::widgetKeyReleaseEvent( QKeyEvent *keyEvent )
|
---|
452 | {
|
---|
453 | Q_UNUSED( keyEvent );
|
---|
454 | }
|
---|
455 |
|
---|
456 | //! \return Parent widget, where the rescaling happens
|
---|
457 | QWidget *QwtMagnifier::parentWidget()
|
---|
458 | {
|
---|
459 | if ( parent()->inherits( "QWidget" ) )
|
---|
460 | return ( QWidget * )parent();
|
---|
461 |
|
---|
462 | return NULL;
|
---|
463 | }
|
---|
464 |
|
---|
465 | //! \return Parent widget, where the rescaling happens
|
---|
466 | const QWidget *QwtMagnifier::parentWidget() const
|
---|
467 | {
|
---|
468 | if ( parent()->inherits( "QWidget" ) )
|
---|
469 | return ( const QWidget * )parent();
|
---|
470 |
|
---|
471 | return NULL;
|
---|
472 | }
|
---|
473 |
|
---|