Revision control
++ // 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
++ // Qt-Security score:significant
++
++ #include "qsignaltransition.h"
++ #include "qsignaltransition_p.h"
++ #include "qstate.h"
++ #include "qstate_p.h"
++ #include "qstatemachine.h"
++ #include "qstatemachine_p.h"
++ #include <qdebug.h>
++
++ QT_BEGIN_NAMESPACE
++
++ /*!
++ \class QSignalTransition
++ \inmodule QtStateMachine
++
++ \brief The QSignalTransition class provides a transition based on a Qt signal.
++
++ \since 4.6
++ \ingroup statemachine
++
++ Typically you would use the overload of QState::addTransition() that takes a
++ sender and signal as arguments, rather than creating QSignalTransition
++ objects directly. QSignalTransition is part of \l{Qt State Machine Overview}
++ {Qt State Machine Framework}.
++
++ You can subclass QSignalTransition and reimplement eventTest() to make a
++ signal transition conditional; the event object passed to eventTest() will
++ be a QStateMachine::SignalEvent object. Example:
++
++ \code
++ class CheckedTransition : public QSignalTransition
++ {
++ public:
++ CheckedTransition(QCheckBox *check)
++ : QSignalTransition(check, SIGNAL(stateChanged(int))) {}
++ protected:
++ bool eventTest(QEvent *e) {
++ if (!QSignalTransition::eventTest(e))
++ return false;
++ QStateMachine::SignalEvent *se = static_cast<QStateMachine::SignalEvent*>(e);
++ return (se->arguments().at(0).toInt() == Qt::Checked);
++ }
++ };
++
++ ...
++
++ QCheckBox *check = new QCheckBox();
++ check->setTristate(true);
++
++ QState *s1 = new QState();
++ QState *s2 = new QState();
++ CheckedTransition *t1 = new CheckedTransition(check);
++ t1->setTargetState(s2);
++ s1->addTransition(t1);
++ \endcode
++ */
++
++ /*!
++ \property QSignalTransition::senderObject
++
++ \brief the sender object that this signal transition is associated with
++ */
++
++ /*!
++ \property QSignalTransition::signal
++
++ \brief the signal that this signal transition is associated with
++ */
++
++ QSignalTransitionPrivate::QSignalTransitionPrivate()
++ {
++ signalIndex = -1;
++ }
++
++ void QSignalTransitionPrivate::unregister()
++ {
++ Q_Q(QSignalTransition);
++ if ((signalIndex == -1) || !machine())
++ return;
++ QStateMachinePrivate::get(machine())->unregisterSignalTransition(q);
++ }
++
++ void QSignalTransitionPrivate::maybeRegister()
++ {
++ Q_Q(QSignalTransition);
++ if (QStateMachine *mach = machine())
++ QStateMachinePrivate::get(mach)->maybeRegisterSignalTransition(q);
++ }
++
++ /*!
++ Constructs a new signal transition with the given \a sourceState.
++ */
++ QSignalTransition::QSignalTransition(QState *sourceState)
++ : QAbstractTransition(*new QSignalTransitionPrivate, sourceState)
++ {
++ }
++
++ /*!
++ Constructs a new signal transition associated with the given \a signal of
++ the given \a sender, and with the given \a sourceState.
++ */
++ QSignalTransition::QSignalTransition(const QObject *sender, const char *signal,
++ QState *sourceState)
++ : QAbstractTransition(*new QSignalTransitionPrivate, sourceState)
++ {
++ Q_D(QSignalTransition);
++ d->senderObject.setValueBypassingBindings(sender);
++ d->signal.setValueBypassingBindings(signal);
++ d->maybeRegister();
++ }
++
++ /*!
++ \fn template <typename PointerToMemberFunction> QSignalTransition::QSignalTransition(const QObject *sender, PointerToMemberFunction signal, QState *sourceState)
++ \since 5.7
++ \overload
++
++ Constructs a new signal transition associated with the given \a signal of
++ the given \a sender object and with the given \a sourceState.
++ This constructor is enabled if the compiler supports delegating constructors,
++ as indicated by the presence of the macro Q_COMPILER_DELEGATING_CONSTRUCTORS.
++ */
++
++ /*!
++ Destroys this signal transition.
++ */
++ QSignalTransition::~QSignalTransition()
++ {
++ }
++
++ /*!
++ Returns the sender object associated with this signal transition.
++ */
++ const QObject *QSignalTransition::senderObject() const
++ {
++ Q_D(const QSignalTransition);
++ return d->senderObject;
++ }
++
++ /*!
++ Sets the \a sender object associated with this signal transition.
++ */
++ void QSignalTransition::setSenderObject(const QObject *sender)
++ {
++ Q_D(QSignalTransition);
++ d->senderObject.removeBindingUnlessInWrapper();
++ if (sender == d->senderObject.valueBypassingBindings())
++ return;
++ d->unregister();
++ d->senderObject.setValueBypassingBindings(sender);
++ d->maybeRegister();
++ d->senderObject.notify();
++ emit senderObjectChanged(QPrivateSignal());
++ }
++
++ QBindable<const QObject*> QSignalTransition::bindableSenderObject()
++ {
++ Q_D(QSignalTransition);
++ return &d->senderObject;
++ }
++
++ /*!
++ Returns the signal associated with this signal transition.
++ */
++ QByteArray QSignalTransition::signal() const
++ {
++ Q_D(const QSignalTransition);
++ return d->signal;
++ }
++
++ /*!
++ Sets the \a signal associated with this signal transition.
++ */
++ void QSignalTransition::setSignal(const QByteArray &signal)
++ {
++ Q_D(QSignalTransition);
++ d->signal.removeBindingUnlessInWrapper();
++ if (signal == d->signal.valueBypassingBindings())
++ return;
++ d->unregister();
++ d->signal.setValueBypassingBindings(signal);
++ d->maybeRegister();
++ d->signal.notify();
++ emit signalChanged(QPrivateSignal());
++ }
++
++ QBindable<QByteArray> QSignalTransition::bindableSignal()
++ {
++ Q_D(QSignalTransition);
++ return &d->signal;
++ }
++
++ /*!
++ \reimp
++
++ The default implementation returns \c true if the \a event is a
++ QStateMachine::SignalEvent object and the event's sender and signal index
++ match this transition, and returns \c false otherwise.
++ */
++ bool QSignalTransition::eventTest(QEvent *event)
++ {
++ Q_D(const QSignalTransition);
++ if (event->type() == QEvent::StateMachineSignal) {
++ if (d->signalIndex == -1)
++ return false;
++ QStateMachine::SignalEvent *se = static_cast<QStateMachine::SignalEvent*>(event);
++ return (se->sender() == d->senderObject.value())
++ && (se->signalIndex() == d->signalIndex);
++ }
++ return false;
++ }
++
++ /*!
++ \reimp
++ */
++ void QSignalTransition::onTransition(QEvent *event)
++ {
++ Q_UNUSED(event);
++ }
++
++ /*!
++ \reimp
++ */
++ bool QSignalTransition::event(QEvent *e)
++ {
++ return QAbstractTransition::event(e);
++ }
++
++ /*!
++ \fn QSignalTransition::senderObjectChanged()
++ \since 5.4
++
++ This signal is emitted when the senderObject property is changed.
++
++ \sa QSignalTransition::senderObject
++ */
++
++ /*!
++ \fn QSignalTransition::signalChanged()
++ \since 5.4
++
++ This signal is emitted when the signal property is changed.
++
++ \sa QSignalTransition::signal
++ */
++
++ void QSignalTransitionPrivate::callOnTransition(QEvent *e)
++ {
++ Q_Q(QSignalTransition);
++
++ if (e->type() == QEvent::StateMachineSignal) {
++ QStateMachine::SignalEvent *se = static_cast<QStateMachine::SignalEvent *>(e);
++ int savedSignalIndex = se->m_signalIndex;
++ se->m_signalIndex = originalSignalIndex;
++ q->onTransition(e);
++ se->m_signalIndex = savedSignalIndex;
++ } else {
++ q->onTransition(e);
++ }
++ }
++
++
++ QT_END_NAMESPACE
++
++ #include "moc_qsignaltransition.cpp"