Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qquickwheelhandler.cpp
Go to the documentation of this file.
1// Copyright (C) 2020 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
6#include <QtQuick/private/qquickitem_p.h>
7#include <QLoggingCategory>
8#include <QtMath>
9
11
12Q_LOGGING_CATEGORY(lcWheelHandler, "qt.quick.handler.wheel")
13
14
57
68{
69 Q_D(const QQuickWheelHandler);
70 return d->orientation;
71}
72
74{
76 if (d->orientation == orientation)
77 return;
78
79 d->orientation = orientation;
81}
82
97{
98 Q_D(const QQuickWheelHandler);
99 return d->invertible;
100}
101
103{
105 if (d->invertible == invertible)
106 return;
107
108 d->invertible = invertible;
110}
111
131{
132 Q_D(const QQuickWheelHandler);
133 return d->activeTimeout;
134}
135
137{
139 if (qFuzzyCompare(d->activeTimeout, timeout))
140 return;
141
142 if (timeout < 0) {
143 qWarning("activeTimeout must be positive");
144 return;
145 }
146
147 d->activeTimeout = timeout;
149}
150
169{
170 Q_D(const QQuickWheelHandler);
171 return d->rotation * d->rotationScale;
172}
173
175{
177 if (qFuzzyCompare(d->rotation, rotation / d->rotationScale))
178 return;
179
180 d->rotation = rotation / d->rotationScale;
182}
183
194{
195 Q_D(const QQuickWheelHandler);
196 return d->rotationScale;
197}
198
200{
202 if (qFuzzyCompare(d->rotationScale, rotationScale))
203 return;
205 qWarning("rotationScale cannot be set to zero");
206 return;
207 }
208
209 d->rotationScale = rotationScale;
211}
212
243{
244 Q_D(const QQuickWheelHandler);
245 return d->propertyName;
246}
247
249{
251 if (d->propertyName == propertyName)
252 return;
253
254 d->propertyName = propertyName;
255 d->metaPropertyDirty = true;
257}
258
278{
279 Q_D(const QQuickWheelHandler);
280 return d->targetScaleMultiplier;
281}
282
284{
286 if (qFuzzyCompare(d->targetScaleMultiplier, targetScaleMultiplier))
287 return;
288
289 d->targetScaleMultiplier = targetScaleMultiplier;
291}
292
307{
308 Q_D(const QQuickWheelHandler);
309 return d->targetTransformAroundCursor;
310}
311
313{
315 if (d->targetTransformAroundCursor == ttac)
316 return;
317
318 d->targetTransformAroundCursor = ttac;
320}
321
330{
331 Q_D(const QQuickWheelHandler);
332 return d->blocking;
333}
334
336{
338 if (d->blocking == blocking)
339 return;
340
341 d->blocking = blocking;
342 emit blockingChanged();
343}
344
346{
347 if (!event)
348 return false;
349 if (event->type() != QEvent::Wheel)
350 return false;
351 QWheelEvent *we = static_cast<QWheelEvent *>(event);
353 && we->source() != Qt::MouseEventNotSynthesized)
354 return false;
355 if (!active()) {
356 switch (orientation()) {
357 case Qt::Horizontal:
358 if (!(we->angleDelta().x()) && !(we->pixelDelta().x()))
359 return false;
360 break;
361 case Qt::Vertical:
362 if (!(we->angleDelta().y()) && !(we->pixelDelta().y()))
363 return false;
364 break;
365 }
366 }
367 auto &point = event->point(0);
370 return true;
371 }
372 return false;
373}
374
376{
379
380 if (ev->type() != QEvent::Wheel)
381 return;
382 const QWheelEvent *event = static_cast<const QWheelEvent *>(ev);
383 setActive(true); // ScrollEnd will not happen unless it was already active (see setActive(false) below)
384 if (d->blocking)
385 point.setAccepted();
386 qreal inversion = !d->invertible && event->isInverted() ? -1 : 1;
387 qreal angleDelta = inversion * qreal(orientation() == Qt::Horizontal ? event->angleDelta().x() :
388 event->angleDelta().y()) / 8;
389 d->rotation += angleDelta;
391
392 d->wheelEvent.reset(event);
393 emit wheel(&d->wheelEvent);
394 if (!d->propertyName.isEmpty() && target()) {
395 QQuickItem *t = target();
396 // writing target()'s property is done via QMetaProperty::write() so that any registered interceptors can react.
397 if (d->propertyName == QLatin1String("scale")) {
398 qreal multiplier = qPow(d->targetScaleMultiplier, angleDelta * d->rotationScale / 15); // wheel "clicks"
399 const QPointF centroidParentPos = t->parentItem()->mapFromScene(point.scenePosition());
400 const QPointF positionWas = t->position();
401 const qreal scaleWas = t->scale();
402 const qreal activePropertyValue = scaleWas * multiplier;
403 qCDebug(lcWheelHandler) << objectName() << "angle delta" << event->angleDelta() << "pixel delta" << event->pixelDelta()
404 << "@" << point.position() << "in parent" << centroidParentPos
405 << "in scene" << point.scenePosition()
406 << "multiplier" << multiplier << "scale" << scaleWas
407 << "->" << activePropertyValue;
408 d->targetMetaProperty().write(t, activePropertyValue);
409 if (d->targetTransformAroundCursor) {
410 // If an interceptor intervened, scale may now be different than we asked for. Adjust accordingly.
411 multiplier = t->scale() / scaleWas;
412 const QPointF adjPos = QQuickItemPrivate::get(t)->adjustedPosForTransform(
413 centroidParentPos, positionWas, QVector2D(), scaleWas, multiplier, t->rotation(), 0);
414 qCDebug(lcWheelHandler) << "adjusting item pos" << adjPos << "in scene" << t->parentItem()->mapToScene(adjPos);
415 t->setPosition(adjPos);
416 }
417 } else if (d->propertyName == QLatin1String("rotation")) {
418 const QPointF positionWas = t->position();
419 const qreal rotationWas = t->rotation();
420 const qreal activePropertyValue = rotationWas + angleDelta * d->rotationScale;
421 const QPointF centroidParentPos = t->parentItem()->mapFromScene(point.scenePosition());
422 qCDebug(lcWheelHandler) << objectName() << "angle delta" << event->angleDelta() << "pixel delta" << event->pixelDelta()
423 << "@" << point.position() << "in parent" << centroidParentPos
424 << "in scene" << point.scenePosition() << "rotation" << t->rotation()
425 << "->" << activePropertyValue;
426 d->targetMetaProperty().write(t, activePropertyValue);
427 if (d->targetTransformAroundCursor) {
428 // If an interceptor intervened, rotation may now be different than we asked for. Adjust accordingly.
429 const QPointF adjPos = QQuickItemPrivate::get(t)->adjustedPosForTransform(
430 centroidParentPos, positionWas, QVector2D(),
431 t->scale(), 1, rotationWas, t->rotation() - rotationWas);
432 qCDebug(lcWheelHandler) << "adjusting item pos" << adjPos << "in scene" << t->parentItem()->mapToScene(adjPos);
433 t->setPosition(adjPos);
434 }
435 } else {
436 qCDebug(lcWheelHandler) << objectName() << "angle delta" << event->angleDelta() << "scaled" << angleDelta
437 << "total" << d->rotation << "pixel delta" << event->pixelDelta()
438 << "@" << point.position() << "in scene" << point.scenePosition() << "rotation" << t->rotation();
439 qreal delta = 0;
440 if (event->hasPixelDelta()) {
441 delta = inversion * d->rotationScale * qreal(orientation() == Qt::Horizontal ? event->pixelDelta().x() : event->pixelDelta().y());
442 qCDebug(lcWheelHandler) << "changing target" << d->propertyName << "by pixel delta" << delta << "from" << event;
443 } else {
444 delta = angleDelta * d->rotationScale;
445 qCDebug(lcWheelHandler) << "changing target" << d->propertyName << "by scaled angle delta" << delta << "from" << event;
446 }
447 bool ok = false;
448 qreal value = d->targetMetaProperty().read(t).toReal(&ok);
449 if (ok)
450 d->targetMetaProperty().write(t, value + qreal(delta));
451 else
452 qWarning() << "failed to read property" << d->propertyName << "of" << t;
453 }
454 }
455 switch (event->phase()) {
456 case Qt::ScrollEnd:
457 qCDebug(lcWheelHandler) << objectName() << "deactivating due to ScrollEnd phase";
458 setActive(false);
459 break;
461 d->deactivationTimer.start(qRound(d->activeTimeout * 1000), this);
462 break;
463 case Qt::ScrollBegin:
464 case Qt::ScrollUpdate:
466 break;
467 }
468}
469
471{
472 Q_UNUSED(oldTarget);
474 d->metaPropertyDirty = true;
475}
476
478{
480 if (!active())
481 d->deactivationTimer.stop();
482}
483
485{
486 Q_D(const QQuickWheelHandler);
487 if (event->timerId() == d->deactivationTimer.timerId()) {
488 qCDebug(lcWheelHandler) << objectName() << "deactivating due to timeout";
489 setActive(false);
490 }
491}
492
505
507{
508 Q_Q(const QQuickWheelHandler);
509 if (metaPropertyDirty && q->target()) {
510 if (!propertyName.isEmpty()) {
511 const QMetaObject *targetMeta = q->target()->metaObject();
512 metaProperty = targetMeta->property(
513 targetMeta->indexOfProperty(propertyName.toLocal8Bit().constData()));
514 }
515 metaPropertyDirty = false;
516 }
517 return metaProperty;
518}
519
540
541#include "moc_qquickwheelhandler_p.cpp"
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
Definition qbytearray.h:124
The QEventPoint class provides information about a point in a QPointerEvent.
Definition qeventpoint.h:20
\inmodule QtCore
QString objectName
the name of this object
Definition qobject.h:107
\inmodule QtCore\reentrant
Definition qpoint.h:217
A base class for pointer events.
Definition qevent.h:73
static QQuickItemPrivate * get(QQuickItem *item)
The QQuickItem class provides the most basic of all visual items in \l {Qt Quick}.
Definition qquickitem.h:63
QInputDevice::DeviceTypes acceptedDevices
bool wantsPointerEvent(QPointerEvent *event) override
It is the responsibility of this function to decide whether the event could be relevant at all to thi...
bool parentContains(const QEventPoint &point) const
Returns true if margin() > 0 and point is within the margin beyond QQuickItem::boundingRect(),...
virtual bool wantsEventPoint(const QPointerEvent *event, const QEventPoint &point)
Returns true if the given point (as part of event) could be relevant at all to this handler,...
virtual void handleEventPoint(QPointerEvent *event, QEventPoint &point)
QMetaProperty & targetMetaProperty() const
QQuickWheelHandlerPrivate()
\qmlsignal QtQuick::WheelHandler::wheel(WheelEvent event)
void setOrientation(Qt::Orientation orientation)
void timerEvent(QTimerEvent *event) override
This event handler can be reimplemented in a subclass to receive timer events for the object.
void setTargetScaleMultiplier(qreal targetScaleMultiplier)
bool isInvertible() const
\qmlproperty bool QtQuick::WheelHandler::invertible
void onActiveChanged() override
bool wantsPointerEvent(QPointerEvent *event) override
It is the responsibility of this function to decide whether the event could be relevant at all to thi...
void activeTimeoutChanged()
void setInvertible(bool invertible)
void setBlocking(bool blocking)
void wheel(QQuickWheelEvent *event)
void setProperty(const QString &name)
void setTargetTransformAroundCursor(bool ttac)
void setActiveTimeout(qreal timeout)
bool isBlocking() const
\qmlproperty bool QtQuick::WheelHandler::blocking
void setRotation(qreal rotation)
void targetTransformAroundCursorChanged()
void targetScaleMultiplierChanged()
void handleEventPoint(QPointerEvent *event, QEventPoint &point) override
bool isTargetTransformAroundCursor() const
\qmlproperty bool QtQuick::WheelHandler::targetTransformAroundCursor
void rotationScaleChanged()
void setRotationScale(qreal rotationScale)
void onTargetChanged(QQuickItem *oldTarget) override
Qt::Orientation orientation
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:192
QByteArray toLocal8Bit() const &
Definition qstring.h:638
\inmodule QtCore
Definition qcoreevent.h:366
The QVector2D class represents a vector or vertex in 2D space.
Definition qvectornd.h:31
Combined button and popup list for selecting options.
Orientation
Definition qnamespace.h:98
@ Horizontal
Definition qnamespace.h:99
@ Vertical
Definition qnamespace.h:100
@ MouseEventNotSynthesized
@ ScrollBegin
@ ScrollUpdate
@ ScrollMomentum
@ NoScrollPhase
@ ScrollEnd
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
bool qFuzzyCompare(qfloat16 p1, qfloat16 p2) noexcept
Definition qfloat16.h:333
bool qFuzzyIsNull(qfloat16 f) noexcept
Definition qfloat16.h:349
int qRound(qfloat16 d) noexcept
Definition qfloat16.h:327
#define qWarning
Definition qlogging.h:166
#define Q_LOGGING_CATEGORY(name,...)
#define qCDebug(category,...)
auto qPow(T1 x, T2 y)
Definition qmath.h:180
GLbitfield GLuint64 timeout
[4]
GLenum target
struct _cl_event * event
GLdouble GLdouble t
Definition qopenglext.h:243
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
#define emit
#define Q_UNUSED(x)
double qreal
Definition qtypes.h:187
\inmodule QtCore