diff options
Diffstat (limited to 'src/statemachine/qsignaltransition.cpp')
-rw-r--r-- | src/statemachine/qsignaltransition.cpp | 287 |
1 files changed, 287 insertions, 0 deletions
diff --git a/src/statemachine/qsignaltransition.cpp b/src/statemachine/qsignaltransition.cpp new file mode 100644 index 0000000..bc88741 --- /dev/null +++ b/src/statemachine/qsignaltransition.cpp @@ -0,0 +1,287 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#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{The 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() +{ + sender = nullptr; + 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->sender = sender; + d->signal = 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. +*/ +QObject *QSignalTransition::senderObject() const +{ + Q_D(const QSignalTransition); + return const_cast<QObject *>(d->sender); +} + +/*! + Sets the \a sender object associated with this signal transition. +*/ +void QSignalTransition::setSenderObject(const QObject *sender) +{ + Q_D(QSignalTransition); + if (sender == d->sender) + return; + d->unregister(); + d->sender = sender; + d->maybeRegister(); + emit senderObjectChanged(QPrivateSignal()); +} + +/*! + 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); + if (signal == d->signal) + return; + d->unregister(); + d->signal = signal; + d->maybeRegister(); + emit signalChanged(QPrivateSignal()); +} + +/*! + \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->sender) + && (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" |