// Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qeventtransition.h" #include "qeventtransition_p.h" #include "qstate.h" #include "qstate_p.h" #include "qstatemachine.h" #include "qstatemachine_p.h" #include QT_BEGIN_NAMESPACE /*! \class QEventTransition \inmodule QtStateMachine \brief The QEventTransition class provides a QObject-specific transition for Qt events. \since 4.6 \ingroup statemachine A QEventTransition object binds an event to a particular QObject. QEventTransition is part of \l{Qt State Machine Overview}{Qt State Machine Framework}. Example: \code QPushButton *button = ...; QState *s1 = ...; QState *s2 = ...; // If in s1 and the button receives an Enter event, transition to s2 QEventTransition *enterTransition = new QEventTransition(button, QEvent::Enter); enterTransition->setTargetState(s2); s1->addTransition(enterTransition); // If in s2 and the button receives an Exit event, transition back to s1 QEventTransition *leaveTransition = new QEventTransition(button, QEvent::Leave); leaveTransition->setTargetState(s1); s2->addTransition(leaveTransition); \endcode \section1 Subclassing When reimplementing the eventTest() function, you should first call the base implementation to verify that the event is a QStateMachine::WrappedEvent for the proper object and event type. You may then cast the event to a QStateMachine::WrappedEvent and get the original event by calling QStateMachine::WrappedEvent::event(), and perform additional checks on that object. \sa QState::addTransition() */ /*! \property QEventTransition::eventSource \brief the event source that this event transition is associated with */ /*! \property QEventTransition::eventType \brief the type of event that this event transition is associated with */ QEventTransitionPrivate::~QEventTransitionPrivate() { } void QEventTransitionPrivate::unregister() { Q_Q(QEventTransition); if (!registered || !machine()) return; QStateMachinePrivate::get(machine())->unregisterEventTransition(q); } void QEventTransitionPrivate::maybeRegister() { Q_Q(QEventTransition); if (QStateMachine *mach = machine()) QStateMachinePrivate::get(mach)->maybeRegisterEventTransition(q); } /*! Constructs a new QEventTransition object with the given \a sourceState. */ QEventTransition::QEventTransition(QState *sourceState) : QAbstractTransition(*new QEventTransitionPrivate, sourceState) { } /*! Constructs a new QEventTransition object associated with events of the given \a type for the given \a object, and with the given \a sourceState. */ QEventTransition::QEventTransition(QObject *object, QEvent::Type type, QState *sourceState) : QAbstractTransition(*new QEventTransitionPrivate, sourceState) { Q_D(QEventTransition); d->registered = false; d->object.setValueBypassingBindings(object); d->eventType.setValueBypassingBindings(type); d->maybeRegister(); } /*! \internal */ QEventTransition::QEventTransition(QEventTransitionPrivate &dd, QState *parent) : QAbstractTransition(dd, parent) { } /*! \internal */ QEventTransition::QEventTransition(QEventTransitionPrivate &dd, QObject *object, QEvent::Type type, QState *parent) : QAbstractTransition(dd, parent) { Q_D(QEventTransition); d->registered = false; d->object.setValueBypassingBindings(object); d->eventType.setValueBypassingBindings(type); d->maybeRegister(); } /*! Destroys this QObject event transition. */ QEventTransition::~QEventTransition() { } /*! Returns the event type that this event transition is associated with. */ QEvent::Type QEventTransition::eventType() const { Q_D(const QEventTransition); return d->eventType; } /*! Sets the event \a type that this event transition is associated with. */ void QEventTransition::setEventType(QEvent::Type type) { Q_D(QEventTransition); d->eventType.removeBindingUnlessInWrapper(); if (d->eventType.valueBypassingBindings() == type) return; d->unregister(); d->eventType.setValueBypassingBindings(type); d->maybeRegister(); d->eventType.notify(); } QBindable QEventTransition::bindableEventType() { Q_D(QEventTransition); return &d->eventType; } /*! Returns the event source associated with this event transition. */ QObject *QEventTransition::eventSource() const { Q_D(const QEventTransition); return d->object; } /*! Sets the event source associated with this event transition to be the given \a object. */ void QEventTransition::setEventSource(QObject *object) { Q_D(QEventTransition); d->object.removeBindingUnlessInWrapper(); if (d->object.valueBypassingBindings() == object) return; d->unregister(); d->object.setValueBypassingBindings(object); d->maybeRegister(); d->object.notify(); } QBindable QEventTransition::bindableEventSource() { Q_D(QEventTransition); return &d->object; } /*! \reimp */ bool QEventTransition::eventTest(QEvent *event) { Q_D(const QEventTransition); if (event->type() == QEvent::StateMachineWrapped) { QStateMachine::WrappedEvent *we = static_cast(event); return (we->object() == d->object) && (we->event()->type() == d->eventType.value()); } return false; } /*! \reimp */ void QEventTransition::onTransition(QEvent *event) { Q_UNUSED(event); } /*! \reimp */ bool QEventTransition::event(QEvent *e) { return QAbstractTransition::event(e); } QT_END_NAMESPACE #include "moc_qeventtransition.cpp"