1// Copyright (C) 2016 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
4#include "qsignaltransition.h"
5#include "qsignaltransition_p.h"
6#include "qstate.h"
7#include "qstate_p.h"
8#include "qstatemachine.h"
9#include "qstatemachine_p.h"
10#include <qdebug.h>
11
12QT_BEGIN_NAMESPACE
13
14/*!
15 \class QSignalTransition
16 \inmodule QtStateMachine
17
18 \brief The QSignalTransition class provides a transition based on a Qt signal.
19
20 \since 4.6
21 \ingroup statemachine
22
23 Typically you would use the overload of QState::addTransition() that takes a
24 sender and signal as arguments, rather than creating QSignalTransition
25 objects directly. QSignalTransition is part of \l{Qt State Machine Overview}
26 {Qt State Machine Framework}.
27
28 You can subclass QSignalTransition and reimplement eventTest() to make a
29 signal transition conditional; the event object passed to eventTest() will
30 be a QStateMachine::SignalEvent object. Example:
31
32 \code
33 class CheckedTransition : public QSignalTransition
34 {
35 public:
36 CheckedTransition(QCheckBox *check)
37 : QSignalTransition(check, SIGNAL(stateChanged(int))) {}
38 protected:
39 bool eventTest(QEvent *e) {
40 if (!QSignalTransition::eventTest(e))
41 return false;
42 QStateMachine::SignalEvent *se = static_cast<QStateMachine::SignalEvent*>(e);
43 return (se->arguments().at(0).toInt() == Qt::Checked);
44 }
45 };
46
47 ...
48
49 QCheckBox *check = new QCheckBox();
50 check->setTristate(true);
51
52 QState *s1 = new QState();
53 QState *s2 = new QState();
54 CheckedTransition *t1 = new CheckedTransition(check);
55 t1->setTargetState(s2);
56 s1->addTransition(t1);
57 \endcode
58*/
59
60/*!
61 \property QSignalTransition::senderObject
62
63 \brief the sender object that this signal transition is associated with
64*/
65
66/*!
67 \property QSignalTransition::signal
68
69 \brief the signal that this signal transition is associated with
70*/
71
72QSignalTransitionPrivate::QSignalTransitionPrivate()
73{
74 signalIndex = -1;
75}
76
77void QSignalTransitionPrivate::unregister()
78{
79 Q_Q(QSignalTransition);
80 if ((signalIndex == -1) || !machine())
81 return;
82 QStateMachinePrivate::get(q: machine())->unregisterSignalTransition(transition: q);
83}
84
85void QSignalTransitionPrivate::maybeRegister()
86{
87 Q_Q(QSignalTransition);
88 if (QStateMachine *mach = machine())
89 QStateMachinePrivate::get(q: mach)->maybeRegisterSignalTransition(transition: q);
90}
91
92/*!
93 Constructs a new signal transition with the given \a sourceState.
94*/
95QSignalTransition::QSignalTransition(QState *sourceState)
96 : QAbstractTransition(*new QSignalTransitionPrivate, sourceState)
97{
98}
99
100/*!
101 Constructs a new signal transition associated with the given \a signal of
102 the given \a sender, and with the given \a sourceState.
103*/
104QSignalTransition::QSignalTransition(const QObject *sender, const char *signal,
105 QState *sourceState)
106 : QAbstractTransition(*new QSignalTransitionPrivate, sourceState)
107{
108 Q_D(QSignalTransition);
109 d->senderObject.setValueBypassingBindings(sender);
110 d->signal.setValueBypassingBindings(signal);
111 d->maybeRegister();
112}
113
114/*!
115 \fn template <typename PointerToMemberFunction> QSignalTransition::QSignalTransition(const QObject *sender, PointerToMemberFunction signal, QState *sourceState)
116 \since 5.7
117 \overload
118
119 Constructs a new signal transition associated with the given \a signal of
120 the given \a sender object and with the given \a sourceState.
121 This constructor is enabled if the compiler supports delegating constructors,
122 as indicated by the presence of the macro Q_COMPILER_DELEGATING_CONSTRUCTORS.
123*/
124
125/*!
126 Destroys this signal transition.
127*/
128QSignalTransition::~QSignalTransition()
129{
130}
131
132/*!
133 Returns the sender object associated with this signal transition.
134*/
135const QObject *QSignalTransition::senderObject() const
136{
137 Q_D(const QSignalTransition);
138 return d->senderObject;
139}
140
141/*!
142 Sets the \a sender object associated with this signal transition.
143*/
144void QSignalTransition::setSenderObject(const QObject *sender)
145{
146 Q_D(QSignalTransition);
147 d->senderObject.removeBindingUnlessInWrapper();
148 if (sender == d->senderObject.valueBypassingBindings())
149 return;
150 d->unregister();
151 d->senderObject.setValueBypassingBindings(sender);
152 d->maybeRegister();
153 d->senderObject.notify();
154 emit senderObjectChanged(QPrivateSignal());
155}
156
157QBindable<const QObject*> QSignalTransition::bindableSenderObject()
158{
159 Q_D(QSignalTransition);
160 return &d->senderObject;
161}
162
163/*!
164 Returns the signal associated with this signal transition.
165*/
166QByteArray QSignalTransition::signal() const
167{
168 Q_D(const QSignalTransition);
169 return d->signal;
170}
171
172/*!
173 Sets the \a signal associated with this signal transition.
174*/
175void QSignalTransition::setSignal(const QByteArray &signal)
176{
177 Q_D(QSignalTransition);
178 d->signal.removeBindingUnlessInWrapper();
179 if (signal == d->signal.valueBypassingBindings())
180 return;
181 d->unregister();
182 d->signal.setValueBypassingBindings(signal);
183 d->maybeRegister();
184 d->signal.notify();
185 emit signalChanged(QPrivateSignal());
186}
187
188QBindable<QByteArray> QSignalTransition::bindableSignal()
189{
190 Q_D(QSignalTransition);
191 return &d->signal;
192}
193
194/*!
195 \reimp
196
197 The default implementation returns \c true if the \a event is a
198 QStateMachine::SignalEvent object and the event's sender and signal index
199 match this transition, and returns \c false otherwise.
200*/
201bool QSignalTransition::eventTest(QEvent *event)
202{
203 Q_D(const QSignalTransition);
204 if (event->type() == QEvent::StateMachineSignal) {
205 if (d->signalIndex == -1)
206 return false;
207 QStateMachine::SignalEvent *se = static_cast<QStateMachine::SignalEvent*>(event);
208 return (se->sender() == d->senderObject.value())
209 && (se->signalIndex() == d->signalIndex);
210 }
211 return false;
212}
213
214/*!
215 \reimp
216*/
217void QSignalTransition::onTransition(QEvent *event)
218{
219 Q_UNUSED(event);
220}
221
222/*!
223 \reimp
224*/
225bool QSignalTransition::event(QEvent *e)
226{
227 return QAbstractTransition::event(e);
228}
229
230/*!
231 \fn QSignalTransition::senderObjectChanged()
232 \since 5.4
233
234 This signal is emitted when the senderObject property is changed.
235
236 \sa QSignalTransition::senderObject
237*/
238
239/*!
240 \fn QSignalTransition::signalChanged()
241 \since 5.4
242
243 This signal is emitted when the signal property is changed.
244
245 \sa QSignalTransition::signal
246*/
247
248void QSignalTransitionPrivate::callOnTransition(QEvent *e)
249{
250 Q_Q(QSignalTransition);
251
252 if (e->type() == QEvent::StateMachineSignal) {
253 QStateMachine::SignalEvent *se = static_cast<QStateMachine::SignalEvent *>(e);
254 int savedSignalIndex = se->m_signalIndex;
255 se->m_signalIndex = originalSignalIndex;
256 q->onTransition(event: e);
257 se->m_signalIndex = savedSignalIndex;
258 } else {
259 q->onTransition(event: e);
260 }
261}
262
263
264QT_END_NAMESPACE
265
266#include "moc_qsignaltransition.cpp"
267

Provided by KDAB

Privacy Policy
Start learning QML with our Intro Training
Find out more

source code of qtscxml/src/statemachine/qsignaltransition.cpp